@openui5/sap.ui.core 1.119.0 → 1.120.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 (828) hide show
  1. package/THIRDPARTY.txt +6 -6
  2. package/package.json +1 -1
  3. package/src/jquery.sap.global.js +40 -111
  4. package/src/jquery.sap.properties.js +7 -1
  5. package/src/jquery.sap.resources.js +1 -1
  6. package/src/jquery.sap.script.js +5 -3
  7. package/src/jquery.sap.storage.js +6 -3
  8. package/src/sap/base/Event.js +32 -78
  9. package/src/sap/base/Eventing.js +114 -271
  10. package/src/sap/base/Log.js +21 -1
  11. package/src/sap/base/config.js +14 -9
  12. package/src/sap/base/i18n/Formatting.js +378 -250
  13. package/src/sap/base/i18n/LanguageTag.js +64 -66
  14. package/src/sap/base/i18n/Localization.js +124 -85
  15. package/src/sap/base/i18n/ResourceBundle.js +1 -1
  16. package/src/sap/base/i18n/date/CalendarType.js +2 -2
  17. package/src/sap/base/i18n/date/CalendarWeekNumbering.js +2 -2
  18. package/src/sap/base/i18n/date/TimezoneUtils.js +43 -6
  19. package/src/sap/base/util/LoaderExtensions.js +8 -2
  20. package/src/sap/base/util/mixedFetch.js +1 -0
  21. package/src/sap/base/util/resolveReference.js +31 -13
  22. package/src/sap/base/util/restricted/_CancelablePromise.js +1 -1
  23. package/src/sap/base/util/restricted/_castArray.js +1 -1
  24. package/src/sap/base/util/restricted/_compact.js +1 -1
  25. package/src/sap/base/util/restricted/_curry.js +1 -1
  26. package/src/sap/base/util/restricted/_debounce.js +1 -1
  27. package/src/sap/base/util/restricted/_difference.js +1 -1
  28. package/src/sap/base/util/restricted/_differenceBy.js +1 -1
  29. package/src/sap/base/util/restricted/_differenceWith.js +1 -1
  30. package/src/sap/base/util/restricted/_flatMap.js +1 -1
  31. package/src/sap/base/util/restricted/_flatMapDeep.js +1 -1
  32. package/src/sap/base/util/restricted/_flatMapDepth.js +1 -1
  33. package/src/sap/base/util/restricted/_flatten.js +1 -1
  34. package/src/sap/base/util/restricted/_flattenDeep.js +1 -1
  35. package/src/sap/base/util/restricted/_flattenDepth.js +1 -1
  36. package/src/sap/base/util/restricted/_intersection.js +1 -1
  37. package/src/sap/base/util/restricted/_intersectionBy.js +1 -1
  38. package/src/sap/base/util/restricted/_intersectionWith.js +1 -1
  39. package/src/sap/base/util/restricted/_isEqual.js +1 -1
  40. package/src/sap/base/util/restricted/_isEqualWith.js +1 -1
  41. package/src/sap/base/util/restricted/_isNil.js +1 -1
  42. package/src/sap/base/util/restricted/_max.js +1 -1
  43. package/src/sap/base/util/restricted/_merge.js +1 -1
  44. package/src/sap/base/util/restricted/_mergeWith.js +1 -1
  45. package/src/sap/base/util/restricted/_min.js +1 -1
  46. package/src/sap/base/util/restricted/_omit.js +1 -1
  47. package/src/sap/base/util/restricted/_pick.js +1 -1
  48. package/src/sap/base/util/restricted/_pickBy.js +1 -1
  49. package/src/sap/base/util/restricted/_throttle.js +1 -1
  50. package/src/sap/base/util/restricted/_toArray.js +1 -1
  51. package/src/sap/base/util/restricted/_union.js +1 -1
  52. package/src/sap/base/util/restricted/_unionBy.js +1 -1
  53. package/src/sap/base/util/restricted/_unionWith.js +1 -1
  54. package/src/sap/base/util/restricted/_uniq.js +1 -1
  55. package/src/sap/base/util/restricted/_uniqBy.js +1 -1
  56. package/src/sap/base/util/restricted/_uniqWith.js +1 -1
  57. package/src/sap/base/util/restricted/_without.js +1 -1
  58. package/src/sap/base/util/restricted/_xor.js +1 -1
  59. package/src/sap/base/util/restricted/_xorBy.js +1 -1
  60. package/src/sap/base/util/restricted/_xorWith.js +1 -1
  61. package/src/sap/base/util/restricted/_zipObject.js +1 -1
  62. package/src/sap/base/util/restricted/_zipObjectDeep.js +1 -1
  63. package/src/sap/base/util/syncFetch.js +1 -0
  64. package/src/sap/ui/Device.js +3 -3
  65. package/src/sap/ui/Global.js +6 -7
  66. package/src/sap/ui/base/BindingInfo.js +3 -3
  67. package/src/sap/ui/base/BindingParser.js +5 -2
  68. package/src/sap/ui/base/DataType.js +57 -1
  69. package/src/sap/ui/base/DesignTime.js +69 -0
  70. package/src/sap/ui/base/Event.js +2 -2
  71. package/src/sap/ui/base/EventProvider.js +1 -1
  72. package/src/sap/ui/base/ExpressionParser.js +25 -4
  73. package/src/sap/ui/base/Interface.js +1 -1
  74. package/src/sap/ui/base/ManagedObject.js +102 -29
  75. package/src/sap/ui/base/ManagedObjectMetadata.js +29 -31
  76. package/src/sap/ui/base/ManagedObjectObserver.js +1 -0
  77. package/src/sap/ui/base/Metadata.js +3 -3
  78. package/src/sap/ui/base/Object.js +19 -1
  79. package/src/sap/ui/base/ObjectPool.js +1 -1
  80. package/src/sap/ui/core/.library +3 -3
  81. package/src/sap/ui/core/AnimationMode.js +2 -2
  82. package/src/sap/ui/core/AppCacheBuster.js +30 -18
  83. package/src/sap/ui/core/BusyIndicator.js +1 -1
  84. package/src/sap/ui/core/CalendarType.js +6 -0
  85. package/src/sap/ui/core/Component.js +150 -80
  86. package/src/sap/ui/core/ComponentContainer.js +4 -3
  87. package/src/sap/ui/core/ComponentMetadata.js +3 -4
  88. package/src/sap/ui/core/ComponentSupport.js +1 -1
  89. package/src/sap/ui/core/Configuration.js +390 -706
  90. package/src/sap/ui/core/Control.js +1 -1
  91. package/src/sap/ui/core/ControlBehavior.js +37 -28
  92. package/src/sap/ui/core/Core.js +327 -151
  93. package/src/sap/ui/core/CustomData.js +1 -1
  94. package/src/sap/ui/core/DeclarativeSupport.js +3 -1
  95. package/src/sap/ui/core/Element.js +18 -8
  96. package/src/sap/ui/core/ElementMetadata.js +1 -1
  97. package/src/sap/ui/core/EnabledPropagator.js +3 -2
  98. package/src/sap/ui/core/EventBus.js +1 -1
  99. package/src/sap/ui/core/Fragment.js +1 -1
  100. package/src/sap/ui/core/HTML.js +1 -1
  101. package/src/sap/ui/core/History.js +1 -1
  102. package/src/sap/ui/core/Icon.js +1 -1
  103. package/src/sap/ui/core/IndicationColorSupport.js +13 -1
  104. package/src/sap/ui/core/IntervalTrigger.js +1 -1
  105. package/src/sap/ui/core/InvisibleMessage.js +2 -3
  106. package/src/sap/ui/core/InvisibleRenderer.js +1 -1
  107. package/src/sap/ui/core/InvisibleText.js +17 -1
  108. package/src/sap/ui/core/Item.js +1 -1
  109. package/src/sap/ui/core/LabelEnablement.js +8 -1
  110. package/src/sap/ui/core/LayoutData.js +1 -1
  111. package/src/sap/ui/core/Lib.js +195 -29
  112. package/src/sap/ui/core/ListItem.js +1 -1
  113. package/src/sap/ui/core/LocalBusyIndicator.js +1 -1
  114. package/src/sap/ui/core/Locale.js +1 -1
  115. package/src/sap/ui/core/LocaleData.js +118 -32
  116. package/src/sap/ui/core/Manifest.js +4 -2
  117. package/src/sap/ui/core/Message.js +1 -1
  118. package/src/sap/ui/core/Placeholder.js +18 -0
  119. package/src/sap/ui/core/Popup.js +5 -0
  120. package/src/sap/ui/core/RenderManager.js +21 -17
  121. package/src/sap/ui/core/Renderer.js +1 -1
  122. package/src/sap/ui/core/Rendering.js +51 -47
  123. package/src/sap/ui/core/ResizeHandler.js +2 -2
  124. package/src/sap/ui/core/ScrollBar.js +1 -1
  125. package/src/sap/ui/core/SeparatorItem.js +1 -1
  126. package/src/sap/ui/core/Shortcut.js +5 -3
  127. package/src/sap/ui/core/Supportability.js +146 -0
  128. package/src/sap/ui/core/Theming.js +130 -88
  129. package/src/sap/ui/core/Title.js +1 -1
  130. package/src/sap/ui/core/TooltipBase.js +4 -3
  131. package/src/sap/ui/core/UIArea.js +1 -4
  132. package/src/sap/ui/core/UIComponent.js +38 -12
  133. package/src/sap/ui/core/UIComponentMetadata.js +1 -1
  134. package/src/sap/ui/core/ValueStateSupport.js +1 -1
  135. package/src/sap/ui/core/VariantLayoutData.js +1 -1
  136. package/src/sap/ui/core/XMLComposite.js +1 -1
  137. package/src/sap/ui/core/XMLCompositeMetadata.js +1 -1
  138. package/src/sap/ui/core/XMLTemplateProcessor.js +3 -3
  139. package/src/sap/ui/core/_IconRegistry.js +13 -6
  140. package/src/sap/ui/core/cldr/ar.json +143 -137
  141. package/src/sap/ui/core/cldr/ar_EG.json +143 -137
  142. package/src/sap/ui/core/cldr/ar_SA.json +143 -137
  143. package/src/sap/ui/core/cldr/bg.json +423 -423
  144. package/src/sap/ui/core/cldr/ca.json +541 -494
  145. package/src/sap/ui/core/cldr/cs.json +475 -364
  146. package/src/sap/ui/core/cldr/cy.json +656 -477
  147. package/src/sap/ui/core/cldr/da.json +334 -275
  148. package/src/sap/ui/core/cldr/de.json +388 -291
  149. package/src/sap/ui/core/cldr/de_AT.json +388 -291
  150. package/src/sap/ui/core/cldr/de_CH.json +394 -297
  151. package/src/sap/ui/core/cldr/el.json +169 -166
  152. package/src/sap/ui/core/cldr/el_CY.json +169 -166
  153. package/src/sap/ui/core/cldr/en.json +558 -521
  154. package/src/sap/ui/core/cldr/en_AU.json +558 -520
  155. package/src/sap/ui/core/cldr/en_GB.json +476 -439
  156. package/src/sap/ui/core/cldr/en_HK.json +520 -482
  157. package/src/sap/ui/core/cldr/en_IE.json +486 -448
  158. package/src/sap/ui/core/cldr/en_IN.json +466 -428
  159. package/src/sap/ui/core/cldr/en_NZ.json +506 -468
  160. package/src/sap/ui/core/cldr/en_PG.json +506 -468
  161. package/src/sap/ui/core/cldr/en_SG.json +506 -468
  162. package/src/sap/ui/core/cldr/en_ZA.json +486 -448
  163. package/src/sap/ui/core/cldr/es.json +473 -468
  164. package/src/sap/ui/core/cldr/es_AR.json +445 -440
  165. package/src/sap/ui/core/cldr/es_BO.json +479 -474
  166. package/src/sap/ui/core/cldr/es_CL.json +469 -464
  167. package/src/sap/ui/core/cldr/es_CO.json +387 -381
  168. package/src/sap/ui/core/cldr/es_MX.json +502 -497
  169. package/src/sap/ui/core/cldr/es_PE.json +455 -450
  170. package/src/sap/ui/core/cldr/es_UY.json +479 -474
  171. package/src/sap/ui/core/cldr/es_VE.json +499 -494
  172. package/src/sap/ui/core/cldr/et.json +378 -320
  173. package/src/sap/ui/core/cldr/fa.json +104 -104
  174. package/src/sap/ui/core/cldr/fi.json +401 -315
  175. package/src/sap/ui/core/cldr/fr.json +391 -385
  176. package/src/sap/ui/core/cldr/fr_BE.json +391 -385
  177. package/src/sap/ui/core/cldr/fr_CA.json +499 -493
  178. package/src/sap/ui/core/cldr/fr_CH.json +334 -328
  179. package/src/sap/ui/core/cldr/fr_LU.json +391 -385
  180. package/src/sap/ui/core/cldr/he.json +291 -159
  181. package/src/sap/ui/core/cldr/hi.json +157 -128
  182. package/src/sap/ui/core/cldr/hr.json +514 -461
  183. package/src/sap/ui/core/cldr/hu.json +287 -257
  184. package/src/sap/ui/core/cldr/id.json +463 -416
  185. package/src/sap/ui/core/cldr/it.json +468 -413
  186. package/src/sap/ui/core/cldr/it_CH.json +468 -413
  187. package/src/sap/ui/core/cldr/ja.json +98 -61
  188. package/src/sap/ui/core/cldr/kk.json +631 -571
  189. package/src/sap/ui/core/cldr/ko.json +79 -71
  190. package/src/sap/ui/core/cldr/lt.json +361 -270
  191. package/src/sap/ui/core/cldr/lv.json +234 -242
  192. package/src/sap/ui/core/cldr/ms.json +463 -408
  193. package/src/sap/ui/core/cldr/nb.json +176 -143
  194. package/src/sap/ui/core/cldr/nl.json +463 -393
  195. package/src/sap/ui/core/cldr/nl_BE.json +463 -393
  196. package/src/sap/ui/core/cldr/pl.json +633 -344
  197. package/src/sap/ui/core/cldr/pt.json +447 -336
  198. package/src/sap/ui/core/cldr/pt_PT.json +488 -449
  199. package/src/sap/ui/core/cldr/ro.json +477 -383
  200. package/src/sap/ui/core/cldr/ru.json +367 -332
  201. package/src/sap/ui/core/cldr/ru_UA.json +361 -326
  202. package/src/sap/ui/core/cldr/sk.json +502 -537
  203. package/src/sap/ui/core/cldr/sl.json +168 -161
  204. package/src/sap/ui/core/cldr/sr.json +276 -225
  205. package/src/sap/ui/core/cldr/sr_Latn.json +972 -907
  206. package/src/sap/ui/core/cldr/sv.json +420 -346
  207. package/src/sap/ui/core/cldr/th.json +117 -94
  208. package/src/sap/ui/core/cldr/tr.json +413 -359
  209. package/src/sap/ui/core/cldr/uk.json +395 -368
  210. package/src/sap/ui/core/cldr/vi.json +392 -379
  211. package/src/sap/ui/core/cldr/zh_CN.json +91 -33
  212. package/src/sap/ui/core/cldr/zh_HK.json +90 -32
  213. package/src/sap/ui/core/cldr/zh_SG.json +90 -32
  214. package/src/sap/ui/core/cldr/zh_TW.json +75 -51
  215. package/src/sap/ui/core/date/CalendarWeekNumbering.js +6 -0
  216. package/src/sap/ui/core/date/UI5Date.js +1 -1
  217. package/src/sap/ui/core/date/_Calendars.js +5 -2
  218. package/src/sap/ui/core/delegate/ItemNavigation.js +1 -1
  219. package/src/sap/ui/core/delegate/ScrollEnablement.js +1 -1
  220. package/src/sap/ui/core/dnd/DragAndDrop.js +3 -2
  221. package/src/sap/ui/core/dnd/DragDropBase.js +1 -1
  222. package/src/sap/ui/core/dnd/DragDropInfo.js +1 -1
  223. package/src/sap/ui/core/dnd/DragInfo.js +1 -1
  224. package/src/sap/ui/core/dnd/DropInfo.js +1 -1
  225. package/src/sap/ui/core/format/DateFormat.js +33 -21
  226. package/src/sap/ui/core/format/NumberFormat.js +3 -2
  227. package/src/sap/ui/core/format/TimezoneUtil.js +1 -1
  228. package/src/sap/ui/core/getCompatibilityVersion.js +2 -2
  229. package/src/sap/ui/core/hyphenation/Hyphenation.js +1 -1
  230. package/src/sap/ui/core/library.js +128 -8
  231. package/src/sap/ui/core/message/ControlMessageProcessor.js +1 -1
  232. package/src/sap/ui/core/message/Message.js +2 -2
  233. package/src/sap/ui/core/message/MessageManager.js +1 -1
  234. package/src/sap/ui/core/message/MessageParser.js +1 -1
  235. package/src/sap/ui/core/message/MessageProcessor.js +1 -1
  236. package/src/sap/ui/core/message/MessageType.js +2 -1
  237. package/src/sap/ui/core/messagebundle.properties +24 -0
  238. package/src/sap/ui/core/messagebundle_ar.properties +15 -3
  239. package/src/sap/ui/core/messagebundle_bg.properties +14 -2
  240. package/src/sap/ui/core/messagebundle_ca.properties +13 -1
  241. package/src/sap/ui/core/messagebundle_cs.properties +15 -3
  242. package/src/sap/ui/core/messagebundle_cy.properties +16 -4
  243. package/src/sap/ui/core/messagebundle_da.properties +15 -3
  244. package/src/sap/ui/core/messagebundle_de.properties +15 -3
  245. package/src/sap/ui/core/messagebundle_el.properties +16 -4
  246. package/src/sap/ui/core/messagebundle_en.properties +12 -0
  247. package/src/sap/ui/core/messagebundle_en_GB.properties +16 -4
  248. package/src/sap/ui/core/messagebundle_es.properties +15 -3
  249. package/src/sap/ui/core/messagebundle_es_MX.properties +15 -3
  250. package/src/sap/ui/core/messagebundle_et.properties +15 -3
  251. package/src/sap/ui/core/messagebundle_fi.properties +15 -3
  252. package/src/sap/ui/core/messagebundle_fr.properties +15 -3
  253. package/src/sap/ui/core/messagebundle_fr_CA.properties +14 -2
  254. package/src/sap/ui/core/messagebundle_hi.properties +16 -4
  255. package/src/sap/ui/core/messagebundle_hr.properties +14 -2
  256. package/src/sap/ui/core/messagebundle_hu.properties +16 -4
  257. package/src/sap/ui/core/messagebundle_id.properties +15 -3
  258. package/src/sap/ui/core/messagebundle_it.properties +17 -5
  259. package/src/sap/ui/core/messagebundle_iw.properties +15 -3
  260. package/src/sap/ui/core/messagebundle_ja.properties +25 -13
  261. package/src/sap/ui/core/messagebundle_kk.properties +15 -3
  262. package/src/sap/ui/core/messagebundle_ko.properties +14 -2
  263. package/src/sap/ui/core/messagebundle_lt.properties +15 -3
  264. package/src/sap/ui/core/messagebundle_lv.properties +15 -3
  265. package/src/sap/ui/core/messagebundle_mk.properties +352 -0
  266. package/src/sap/ui/core/messagebundle_ms.properties +15 -3
  267. package/src/sap/ui/core/messagebundle_nl.properties +15 -3
  268. package/src/sap/ui/core/messagebundle_no.properties +14 -2
  269. package/src/sap/ui/core/messagebundle_pl.properties +15 -3
  270. package/src/sap/ui/core/messagebundle_pt.properties +15 -3
  271. package/src/sap/ui/core/messagebundle_pt_PT.properties +14 -2
  272. package/src/sap/ui/core/messagebundle_ro.properties +15 -3
  273. package/src/sap/ui/core/messagebundle_ru.properties +15 -3
  274. package/src/sap/ui/core/messagebundle_sh.properties +43 -31
  275. package/src/sap/ui/core/messagebundle_sk.properties +16 -4
  276. package/src/sap/ui/core/messagebundle_sl.properties +15 -3
  277. package/src/sap/ui/core/messagebundle_sv.properties +22 -10
  278. package/src/sap/ui/core/messagebundle_th.properties +15 -3
  279. package/src/sap/ui/core/messagebundle_tr.properties +15 -3
  280. package/src/sap/ui/core/messagebundle_uk.properties +18 -6
  281. package/src/sap/ui/core/messagebundle_vi.properties +18 -6
  282. package/src/sap/ui/core/messagebundle_zh_CN.properties +15 -3
  283. package/src/sap/ui/core/messagebundle_zh_TW.properties +15 -3
  284. package/src/sap/ui/core/mvc/Controller.js +22 -16
  285. package/src/sap/ui/core/mvc/EventHandlerResolver.js +5 -15
  286. package/src/sap/ui/core/mvc/HTMLView.js +2 -2
  287. package/src/sap/ui/core/mvc/JSONView.js +4 -1
  288. package/src/sap/ui/core/mvc/JSONViewRenderer.js +1 -0
  289. package/src/sap/ui/core/mvc/JSView.js +1 -1
  290. package/src/sap/ui/core/mvc/OverrideExecution.js +4 -4
  291. package/src/sap/ui/core/mvc/TemplateView.js +1 -1
  292. package/src/sap/ui/core/mvc/View.js +24 -14
  293. package/src/sap/ui/core/mvc/ViewType.js +2 -0
  294. package/src/sap/ui/core/mvc/XMLView.js +1 -1
  295. package/src/sap/ui/core/plugin/DeclarativeSupport.js +2 -1
  296. package/src/sap/ui/core/plugin/LessSupport.js +3 -1
  297. package/src/sap/ui/core/plugin/TemplatingSupport.js +1 -1
  298. package/src/sap/ui/core/postmessage/Bus.js +1 -1
  299. package/src/sap/ui/core/postmessage/confirmationDialog.js +1 -1
  300. package/src/sap/ui/core/routing/Router.js +2 -4
  301. package/src/sap/ui/core/routing/Target.js +1 -3
  302. package/src/sap/ui/core/routing/Targets.js +2 -3
  303. package/src/sap/ui/core/routing/Views.js +2 -3
  304. package/src/sap/ui/core/routing/async/Target.js +1 -1
  305. package/src/sap/ui/core/rules/Config.support.js +11 -17
  306. package/src/sap/ui/core/search/OpenSearchProvider.js +1 -1
  307. package/src/sap/ui/core/search/SearchProvider.js +1 -1
  308. package/src/sap/ui/core/service/Service.js +1 -1
  309. package/src/sap/ui/core/service/ServiceFactory.js +1 -1
  310. package/src/sap/ui/core/service/ServiceFactoryRegistry.js +1 -1
  311. package/src/sap/ui/core/support/Hotkeys.js +5 -3
  312. package/src/sap/ui/core/support/Plugin.js +1 -1
  313. package/src/sap/ui/core/support/RuleEngineOpaExtension.js +1 -3
  314. package/src/sap/ui/core/support/Support.js +3 -5
  315. package/src/sap/ui/core/support/ToolsAPI.js +15 -11
  316. package/src/sap/ui/core/support/plugins/ControlTree.js +1 -1
  317. package/src/sap/ui/core/support/plugins/Interaction.js +4 -4
  318. package/src/sap/ui/core/support/plugins/LocalStorage.js +1 -1
  319. package/src/sap/ui/core/support/plugins/Performance.js +1 -1
  320. package/src/sap/ui/core/support/plugins/Selector.js +7 -5
  321. package/src/sap/ui/core/support/plugins/TechInfo.js +1 -1
  322. package/src/sap/ui/core/support/plugins/Trace.js +1 -1
  323. package/src/sap/ui/core/support/plugins/ViewInfo.js +1 -1
  324. package/src/sap/ui/core/support/techinfo/TechnicalInfo.js +3 -1
  325. package/src/sap/ui/core/syncStyleClass.js +2 -2
  326. package/src/sap/ui/core/themes/base/fonts/SAP-icons.ttf +0 -0
  327. package/src/sap/ui/core/themes/base/fonts/SAP-icons.woff2 +0 -0
  328. package/src/sap/ui/core/themes/base/global.less +9 -9
  329. package/src/sap/ui/core/theming/Parameters.js +18 -19
  330. package/src/sap/ui/core/theming/ThemeManager.js +23 -4
  331. package/src/sap/ui/core/tmpl/DOMAttribute.js +1 -1
  332. package/src/sap/ui/core/tmpl/DOMElement.js +1 -1
  333. package/src/sap/ui/core/tmpl/HandlebarsTemplate.js +1 -1
  334. package/src/sap/ui/core/tmpl/Template.js +1 -1
  335. package/src/sap/ui/core/tmpl/TemplateControl.js +1 -1
  336. package/src/sap/ui/core/util/AsyncHintsHelper.js +1 -1
  337. package/src/sap/ui/core/util/Export.js +1 -1
  338. package/src/sap/ui/core/util/ExportCell.js +1 -1
  339. package/src/sap/ui/core/util/ExportColumn.js +1 -1
  340. package/src/sap/ui/core/util/ExportRow.js +1 -1
  341. package/src/sap/ui/core/util/ExportType.js +1 -1
  342. package/src/sap/ui/core/util/ExportTypeCSV.js +1 -1
  343. package/src/sap/ui/core/util/File.js +1 -1
  344. package/src/sap/ui/core/util/LibraryInfo.js +1 -1
  345. package/src/sap/ui/core/util/MockServer.js +1 -1
  346. package/src/sap/ui/core/util/PasteHelper.js +1 -1
  347. package/src/sap/ui/core/util/XMLPreprocessor.js +3 -0
  348. package/src/sap/ui/core/util/serializer/HTMLViewSerializer.js +1 -1
  349. package/src/sap/ui/core/util/serializer/Serializer.js +1 -1
  350. package/src/sap/ui/core/util/serializer/ViewSerializer.js +4 -4
  351. package/src/sap/ui/core/util/serializer/XMLViewSerializer.js +1 -1
  352. package/src/sap/ui/core/util/serializer/delegate/Delegate.js +1 -1
  353. package/src/sap/ui/core/util/serializer/delegate/HTML.js +1 -1
  354. package/src/sap/ui/core/util/serializer/delegate/XML.js +1 -1
  355. package/src/sap/ui/core/webc/WebComponent.js +1 -1
  356. package/src/sap/ui/core/webc/WebComponentMetadata.js +1 -1
  357. package/src/sap/ui/core/ws/ReadyState.js +1 -1
  358. package/src/sap/ui/core/ws/SapPcpWebSocket.js +1 -1
  359. package/src/sap/ui/core/ws/WebSocket.js +1 -1
  360. package/src/sap/ui/debug/ControlTree.js +1 -1
  361. package/src/sap/ui/debug/DebugEnv.js +29 -7
  362. package/src/sap/ui/debug/PropertyList.js +1 -1
  363. package/src/sap/ui/model/ClientListBinding.js +3 -1
  364. package/src/sap/ui/model/ClientModel.js +1 -1
  365. package/src/sap/ui/model/ClientTreeBinding.js +3 -1
  366. package/src/sap/ui/model/CompositeDataState.js +1 -1
  367. package/src/sap/ui/model/CompositeType.js +1 -1
  368. package/src/sap/ui/model/DataState.js +2 -2
  369. package/src/sap/ui/model/Filter.js +39 -1
  370. package/src/sap/ui/model/FilterProcessor.js +12 -2
  371. package/src/sap/ui/model/ListBinding.js +5 -0
  372. package/src/sap/ui/model/ManagedObjectBindingSupport.js +4 -4
  373. package/src/sap/ui/model/MetaModel.js +1 -1
  374. package/src/sap/ui/model/Model.js +5 -1
  375. package/src/sap/ui/model/SelectionModel.js +1 -1
  376. package/src/sap/ui/model/SimpleType.js +1 -1
  377. package/src/sap/ui/model/TreeAutoExpandMode.js +1 -1
  378. package/src/sap/ui/model/TreeBinding.js +3 -0
  379. package/src/sap/ui/model/Type.js +1 -1
  380. package/src/sap/ui/model/analytics/AnalyticalBinding.js +3 -1
  381. package/src/sap/ui/model/json/JSONListBinding.js +3 -1
  382. package/src/sap/ui/model/json/JSONModel.js +1 -1
  383. package/src/sap/ui/model/json/JSONTreeBinding.js +3 -2
  384. package/src/sap/ui/model/message/MessageListBinding.js +3 -0
  385. package/src/sap/ui/model/message/MessageModel.js +1 -1
  386. package/src/sap/ui/model/odata/AnnotationHelper.js +9 -3
  387. package/src/sap/ui/model/odata/ODataAnnotations.js +1 -1
  388. package/src/sap/ui/model/odata/ODataListBinding.js +3 -0
  389. package/src/sap/ui/model/odata/ODataMessageParser.js +1 -1
  390. package/src/sap/ui/model/odata/ODataMetaModel.js +1 -1
  391. package/src/sap/ui/model/odata/ODataMetadata.js +1 -1
  392. package/src/sap/ui/model/odata/ODataModel.js +9 -5
  393. package/src/sap/ui/model/odata/ODataPropertyBinding.js +1 -2
  394. package/src/sap/ui/model/odata/ODataTreeBinding.js +2 -0
  395. package/src/sap/ui/model/odata/ODataTreeBindingFlat.js +9 -14
  396. package/src/sap/ui/model/odata/type/Boolean.js +1 -1
  397. package/src/sap/ui/model/odata/type/Byte.js +1 -1
  398. package/src/sap/ui/model/odata/type/Currency.js +1 -1
  399. package/src/sap/ui/model/odata/type/Date.js +1 -1
  400. package/src/sap/ui/model/odata/type/DateTime.js +1 -1
  401. package/src/sap/ui/model/odata/type/DateTimeBase.js +1 -1
  402. package/src/sap/ui/model/odata/type/DateTimeOffset.js +1 -1
  403. package/src/sap/ui/model/odata/type/DateTimeWithTimezone.js +1 -1
  404. package/src/sap/ui/model/odata/type/Decimal.js +1 -1
  405. package/src/sap/ui/model/odata/type/Double.js +1 -1
  406. package/src/sap/ui/model/odata/type/Guid.js +1 -1
  407. package/src/sap/ui/model/odata/type/Int.js +1 -1
  408. package/src/sap/ui/model/odata/type/Int16.js +1 -1
  409. package/src/sap/ui/model/odata/type/Int32.js +1 -1
  410. package/src/sap/ui/model/odata/type/Int64.js +1 -1
  411. package/src/sap/ui/model/odata/type/ODataType.js +1 -1
  412. package/src/sap/ui/model/odata/type/Raw.js +1 -1
  413. package/src/sap/ui/model/odata/type/SByte.js +1 -1
  414. package/src/sap/ui/model/odata/type/Single.js +1 -1
  415. package/src/sap/ui/model/odata/type/Stream.js +1 -1
  416. package/src/sap/ui/model/odata/type/String.js +1 -1
  417. package/src/sap/ui/model/odata/type/Time.js +1 -1
  418. package/src/sap/ui/model/odata/type/TimeOfDay.js +1 -1
  419. package/src/sap/ui/model/odata/type/Unit.js +1 -1
  420. package/src/sap/ui/model/odata/v2/Context.js +1 -1
  421. package/src/sap/ui/model/odata/v2/ODataAnnotations.js +1 -1
  422. package/src/sap/ui/model/odata/v2/ODataListBinding.js +35 -13
  423. package/src/sap/ui/model/odata/v2/ODataModel.js +21 -8
  424. package/src/sap/ui/model/odata/v2/ODataTreeBinding.js +33 -2
  425. package/src/sap/ui/model/odata/v4/Context.js +81 -7
  426. package/src/sap/ui/model/odata/v4/ODataContextBinding.js +1 -1
  427. package/src/sap/ui/model/odata/v4/ODataListBinding.js +217 -75
  428. package/src/sap/ui/model/odata/v4/ODataMetaModel.js +1 -1
  429. package/src/sap/ui/model/odata/v4/ODataModel.js +6 -6
  430. package/src/sap/ui/model/odata/v4/ODataPropertyBinding.js +1 -1
  431. package/src/sap/ui/model/odata/v4/lib/_AggregationCache.js +406 -199
  432. package/src/sap/ui/model/odata/v4/lib/_AggregationHelper.js +12 -7
  433. package/src/sap/ui/model/odata/v4/lib/_Cache.js +53 -30
  434. package/src/sap/ui/model/odata/v4/lib/_Helper.js +6 -4
  435. package/src/sap/ui/model/odata/v4/lib/_Requestor.js +6 -6
  436. package/src/sap/ui/model/resource/ResourceModel.js +5 -6
  437. package/src/sap/ui/model/type/Boolean.js +1 -1
  438. package/src/sap/ui/model/type/Currency.js +1 -1
  439. package/src/sap/ui/model/type/Date.js +1 -1
  440. package/src/sap/ui/model/type/DateInterval.js +1 -1
  441. package/src/sap/ui/model/type/DateTime.js +1 -1
  442. package/src/sap/ui/model/type/DateTimeInterval.js +1 -1
  443. package/src/sap/ui/model/type/FileSize.js +1 -1
  444. package/src/sap/ui/model/type/Float.js +1 -1
  445. package/src/sap/ui/model/type/Integer.js +1 -1
  446. package/src/sap/ui/model/type/String.js +1 -1
  447. package/src/sap/ui/model/type/Time.js +1 -1
  448. package/src/sap/ui/model/type/TimeInterval.js +1 -1
  449. package/src/sap/ui/model/type/Unit.js +1 -1
  450. package/src/sap/ui/model/xml/XMLListBinding.js +3 -0
  451. package/src/sap/ui/model/xml/XMLModel.js +1 -1
  452. package/src/sap/ui/model/xml/XMLTreeBinding.js +3 -0
  453. package/src/sap/ui/performance/BeaconRequest.js +2 -2
  454. package/src/sap/ui/qunit/QUnitUtils.js +64 -45
  455. package/src/sap/ui/qunit/qunit-coverage.js +6 -0
  456. package/src/sap/ui/qunit/utils/ControlIterator.js +31 -1
  457. package/src/sap/ui/qunit/utils/MemoryLeakCheck.js +1 -1
  458. package/src/sap/ui/security/Security.js +128 -0
  459. package/src/sap/ui/test/BlanketReporter.js +2 -3
  460. package/src/sap/ui/test/BlanketReporterUI.view.xml +1 -1
  461. package/src/sap/ui/test/BranchTracking.js +2 -3
  462. package/src/sap/ui/test/ModuleTracking.js +48 -20
  463. package/src/sap/ui/test/OpaExtension.js +3 -3
  464. package/src/sap/ui/test/OpaPlugin.js +16 -6
  465. package/src/sap/ui/test/TestUtils.js +7 -4
  466. package/src/sap/ui/test/_BrowserLogCollector.js +1 -0
  467. package/src/sap/ui/test/_ControlFinder.js +3 -2
  468. package/src/sap/ui/test/_LogCollector.js +1 -0
  469. package/src/sap/ui/test/_UsageReport.js +115 -114
  470. package/src/sap/ui/test/actions/EnterText.js +20 -2
  471. package/src/sap/ui/test/autowaiter/WaiterBase.js +1 -0
  472. package/src/sap/ui/test/autowaiter/_moduleWaiter.js +1 -2
  473. package/src/sap/ui/test/autowaiter/_timeoutWaiter.js +1 -1
  474. package/src/sap/ui/test/generic/GenericTestCollection.js +5 -0
  475. package/src/sap/ui/test/generic/TestBase.js +1 -1
  476. package/src/sap/ui/test/generic/Utils.js +1 -1
  477. package/src/sap/ui/test/matchers/LabelFor.js +2 -12
  478. package/src/sap/ui/test/matchers/Matcher.js +1 -1
  479. package/src/sap/ui/test/pipelines/PipelineFactory.js +1 -0
  480. package/src/sap/ui/test/selectors/_Selector.js +1 -1
  481. package/src/sap/ui/util/Storage.js +1 -1
  482. package/src/ui5loader-autoconfig.js +84 -11
  483. package/test/sap/ui/core/demokit/sample/RoutingNestedComponent/localService/mockserver.js +3 -4
  484. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/ChartAnnotation.fragment.xml +7 -7
  485. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/Component.js +2 -3
  486. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/Detail.view.xml +12 -13
  487. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/Facets.fragment.xml +4 -4
  488. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/Field.fragment.xml +8 -8
  489. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/FormFacet.fragment.xml +3 -5
  490. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/LabeledField.fragment.xml +3 -3
  491. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/Table.fragment.xml +10 -10
  492. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/TableFacet.fragment.xml +3 -3
  493. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/extension/HeaderInfo.fragment.xml +1 -1
  494. package/test/sap/ui/core/demokit/sample/ViewTemplate/tiny/Field.fragment.xml +2 -2
  495. package/test/sap/ui/core/demokit/sample/ViewTemplate/tiny/Template.view.xml +19 -21
  496. package/test/sap/ui/core/demokit/sample/ViewTemplate/types/TemplateV4.view.xml +2 -2
  497. package/test/sap/ui/core/demokit/sample/ViewTemplate/valuelist/Component.js +2 -3
  498. package/test/sap/ui/core/demokit/sample/common/SandboxModelHelper.js +2 -3
  499. package/test/sap/ui/core/demokit/sample/common/ValueHelp.js +2 -3
  500. package/test/sap/ui/core/demokit/sample/common/pages/Any.js +7 -8
  501. package/test/sap/ui/core/demokit/sample/odata/v4/Ancestry/Main.controller.js +15 -6
  502. package/test/sap/ui/core/demokit/sample/odata/v4/DataAggregation/DataAggregation.controller.js +2 -3
  503. package/test/sap/ui/core/demokit/sample/odata/v4/FlatDataAggregation/FlatDataAggregation.controller.js +3 -4
  504. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/Main.controller.js +39 -16
  505. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/Main.view.xml +18 -21
  506. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/data/all.json +509 -395
  507. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/data/metadata.xml +586 -422
  508. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/manifest.json +1 -1
  509. package/test/sap/ui/core/demokit/sample/odata/v4/LateProperties/Main.controller.js +2 -3
  510. package/test/sap/ui/core/demokit/sample/odata/v4/ListBindingTemplate/Facets.fragment.xml +22 -23
  511. package/test/sap/ui/core/demokit/sample/odata/v4/ListBindingTemplate/FormattedText.fragment.xml +2 -3
  512. package/test/sap/ui/core/demokit/sample/odata/v4/ListBindingTemplate/Main.view.xml +7 -7
  513. package/test/sap/ui/core/demokit/sample/odata/v4/MultipleInlineCreationRowsGrid/Main.controller.js +0 -3
  514. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/RecursiveHierarchy.controller.js +54 -9
  515. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/RecursiveHierarchy.view.xml +34 -9
  516. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/SandboxModel.js +156 -23
  517. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/Main.view.xml +3 -2
  518. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrdersTemplate/Facets.fragment.xml +22 -23
  519. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrdersTemplate/FormattedText.fragment.xml +2 -3
  520. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrdersTemplate/Main.view.xml +5 -5
  521. package/test/sap/ui/core/demokit/sample/odata/v4/ServerDrivenPaging/Main.controller.js +2 -3
  522. package/test/sap/ui/core/demokit/tutorial/databinding/01/ui5.yaml +2 -2
  523. package/test/sap/ui/core/demokit/tutorial/databinding/02/ui5.yaml +2 -2
  524. package/test/sap/ui/core/demokit/tutorial/databinding/03/ui5.yaml +2 -2
  525. package/test/sap/ui/core/demokit/tutorial/databinding/04/ui5.yaml +2 -2
  526. package/test/sap/ui/core/demokit/tutorial/databinding/05/ui5.yaml +2 -2
  527. package/test/sap/ui/core/demokit/tutorial/databinding/06/ui5.yaml +2 -2
  528. package/test/sap/ui/core/demokit/tutorial/databinding/07/ui5.yaml +2 -2
  529. package/test/sap/ui/core/demokit/tutorial/databinding/08/ui5.yaml +2 -2
  530. package/test/sap/ui/core/demokit/tutorial/databinding/09/ui5.yaml +2 -2
  531. package/test/sap/ui/core/demokit/tutorial/databinding/10/ui5.yaml +2 -2
  532. package/test/sap/ui/core/demokit/tutorial/databinding/11/ui5.yaml +2 -2
  533. package/test/sap/ui/core/demokit/tutorial/databinding/12/ui5.yaml +2 -2
  534. package/test/sap/ui/core/demokit/tutorial/databinding/13/ui5.yaml +2 -2
  535. package/test/sap/ui/core/demokit/tutorial/databinding/14/ui5.yaml +2 -2
  536. package/test/sap/ui/core/demokit/tutorial/databinding/15/ui5.yaml +2 -2
  537. package/test/sap/ui/core/demokit/tutorial/mockserver/01/ui5.yaml +2 -2
  538. package/test/sap/ui/core/demokit/tutorial/mockserver/02/ui5.yaml +2 -2
  539. package/test/sap/ui/core/demokit/tutorial/mockserver/03/ui5.yaml +2 -2
  540. package/test/sap/ui/core/demokit/tutorial/mockserver/04/ui5.yaml +2 -2
  541. package/test/sap/ui/core/demokit/tutorial/navigation/01/ui5.yaml +2 -2
  542. package/test/sap/ui/core/demokit/tutorial/navigation/02/ui5.yaml +2 -2
  543. package/test/sap/ui/core/demokit/tutorial/navigation/03/ui5.yaml +2 -2
  544. package/test/sap/ui/core/demokit/tutorial/navigation/04/ui5.yaml +2 -2
  545. package/test/sap/ui/core/demokit/tutorial/navigation/05/ui5.yaml +2 -2
  546. package/test/sap/ui/core/demokit/tutorial/navigation/06/ui5.yaml +2 -2
  547. package/test/sap/ui/core/demokit/tutorial/navigation/07/ui5.yaml +2 -2
  548. package/test/sap/ui/core/demokit/tutorial/navigation/08/ui5.yaml +2 -2
  549. package/test/sap/ui/core/demokit/tutorial/navigation/09/ui5.yaml +2 -2
  550. package/test/sap/ui/core/demokit/tutorial/navigation/10/ui5.yaml +2 -2
  551. package/test/sap/ui/core/demokit/tutorial/navigation/11/ui5.yaml +2 -2
  552. package/test/sap/ui/core/demokit/tutorial/navigation/12/ui5.yaml +2 -2
  553. package/test/sap/ui/core/demokit/tutorial/navigation/13/ui5.yaml +2 -2
  554. package/test/sap/ui/core/demokit/tutorial/navigation/14/ui5.yaml +2 -2
  555. package/test/sap/ui/core/demokit/tutorial/navigation/15/ui5.yaml +2 -2
  556. package/test/sap/ui/core/demokit/tutorial/navigation/16/ui5.yaml +2 -2
  557. package/test/sap/ui/core/demokit/tutorial/navigation/17/ui5.yaml +2 -2
  558. package/test/sap/ui/core/demokit/tutorial/odatav4/01/ui5.yaml +2 -2
  559. package/test/sap/ui/core/demokit/tutorial/odatav4/02/ui5.yaml +2 -2
  560. package/test/sap/ui/core/demokit/tutorial/odatav4/03/ui5.yaml +2 -2
  561. package/test/sap/ui/core/demokit/tutorial/odatav4/04/ui5.yaml +2 -2
  562. package/test/sap/ui/core/demokit/tutorial/odatav4/05/ui5.yaml +2 -2
  563. package/test/sap/ui/core/demokit/tutorial/odatav4/06/ui5.yaml +2 -2
  564. package/test/sap/ui/core/demokit/tutorial/odatav4/07/ui5.yaml +2 -2
  565. package/test/sap/ui/core/demokit/tutorial/odatav4/08/ui5.yaml +2 -2
  566. package/test/sap/ui/core/demokit/tutorial/odatav4/09/ui5.yaml +2 -2
  567. package/test/sap/ui/core/demokit/tutorial/odatav4/10/ui5.yaml +2 -2
  568. package/test/sap/ui/core/demokit/tutorial/odatav4/11/ui5.yaml +2 -2
  569. package/test/sap/ui/core/demokit/tutorial/troubleshooting/01/ui5.yaml +2 -2
  570. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/Component.js +2 -3
  571. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/Main.view.xml +1 -1
  572. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/SandboxModel.js +2 -3
  573. package/test/sap/ui/core/qunit/CompositeBinding.qunit.js +18 -0
  574. package/test/sap/ui/core/qunit/ControlRenderer.qunit.js +4 -3
  575. package/test/sap/ui/core/qunit/Core.qunit.js +5 -14
  576. package/test/sap/ui/core/qunit/Core_libraryPreloadFiles.qunit.js +4 -4
  577. package/test/sap/ui/core/qunit/Core_libraryPreloadFiles_unavoidablyUsingEval.qunit.js +6 -6
  578. package/test/sap/ui/core/qunit/Core_unavoidablyUsingEval.qunit.js +31 -30
  579. package/test/sap/ui/core/qunit/DataState.qunit.js +7 -4
  580. package/test/sap/ui/core/qunit/DuplicateIds.qunit.js +3 -0
  581. package/test/sap/ui/core/qunit/DuplicateIds_noError.qunit.js +4 -0
  582. package/test/sap/ui/core/qunit/Element_metadata_renderer.qunit.js +6 -0
  583. package/test/sap/ui/core/qunit/ExpressionParser.qunit.js +144 -85
  584. package/test/sap/ui/core/qunit/HTML.qunit.js +87 -84
  585. package/test/sap/ui/core/qunit/InvisibleText.qunit.js +22 -1
  586. package/test/sap/ui/core/qunit/LRUPersistentCache.qunit.js +4 -4
  587. package/test/sap/ui/core/qunit/Lib.qunit.js +22 -1
  588. package/test/sap/ui/core/qunit/ListBinding.qunit.js +14 -1
  589. package/test/sap/ui/core/qunit/ManagedObject.qunit.js +5 -2
  590. package/test/sap/ui/core/qunit/ManagedObjectMetadata.qunit.js +41 -40
  591. package/test/sap/ui/core/qunit/ManagedObjectModel.qunit.js +2 -1
  592. package/test/sap/ui/core/qunit/{ManagedObject_noBoot.qunit.js → ManagedObject_BindingParser.qunit.js} +10 -9
  593. package/test/sap/ui/core/qunit/Object.qunit.js +36 -0
  594. package/test/sap/ui/core/qunit/RenderManager.qunit.js +86 -94
  595. package/test/sap/ui/core/qunit/ShortcutHints.qunit.js +11 -97
  596. package/test/sap/ui/core/qunit/StaticBinding.qunit.js +3 -0
  597. package/test/sap/ui/core/qunit/UIArea.qunit.js +34 -35
  598. package/test/sap/ui/core/qunit/analytics/AnalyticalTreeBindingAdapter.qunit.js +3 -0
  599. package/test/sap/ui/core/qunit/analytics/ODataModelAdapter.qunit.js +3 -0
  600. package/test/sap/ui/core/qunit/analytics/odata4analytics.qunit.js +3 -0
  601. package/test/sap/ui/core/qunit/app/DesignMode_controllerDeactivated.qunit.js +5 -6
  602. package/test/sap/ui/core/qunit/app/DesignMode_suppressedDeactivation.qunit.js +5 -6
  603. package/test/sap/ui/core/qunit/app/MessageListBinding.qunit.js +3 -0
  604. package/test/sap/ui/core/qunit/app/_createDesignModeTests_legacyAPIs.qunit.js +8 -10
  605. package/test/sap/ui/core/qunit/base/Config_cascade.qunit.js +2 -2
  606. package/test/sap/ui/core/qunit/base/i18n/Formatting.qunit.js +30 -30
  607. package/test/sap/ui/core/qunit/base/i18n/ResourceBundle.qunit.js +123 -10
  608. package/test/sap/ui/core/qunit/base/util/resolveReference.qunit.js +9 -0
  609. package/test/sap/ui/core/qunit/base/util/testdata/MyModule.js +5 -0
  610. package/test/sap/ui/core/qunit/bootstrap/BootstrapCustomBootTaskPreloadCss.beforeBootstrap.qunit.js +4 -2
  611. package/test/sap/ui/core/qunit/bootstrap/BootstrapMinimal.qunit.html +1 -0
  612. package/test/sap/ui/core/qunit/bootstrap/BootstrapPreload.qunit.js +9 -10
  613. package/test/sap/ui/core/qunit/bootstrap/BootstrapPreload_legacyAPIs.qunit.js +0 -2
  614. package/test/sap/ui/core/qunit/bootstrap/BootstrapWithinBody.qunit.html +2 -1
  615. package/test/sap/ui/core/qunit/bootstrap/BootstrapWithinHead.qunit.html +2 -1
  616. package/test/sap/ui/core/qunit/bootstrap/Configuration.qunit.js +122 -266
  617. package/test/sap/ui/core/qunit/bootstrap/ConfigurationFlexibility_LibConfigured.qunit.html +22 -0
  618. package/test/sap/ui/core/qunit/bootstrap/ConfigurationFlexibility_LibConfigured.qunit.js +22 -0
  619. package/test/sap/ui/core/qunit/bootstrap/ConfigurationFlexibility_LibLoaded.qunit.html +22 -0
  620. package/test/sap/ui/core/qunit/bootstrap/ConfigurationFlexibility_LibLoaded.qunit.js +16 -0
  621. package/test/sap/ui/core/qunit/bootstrap/ConfigurationFlexibility_LibNotLoaded.qunit.html +22 -0
  622. package/test/sap/ui/core/qunit/bootstrap/ConfigurationFlexibility_LibNotLoaded.qunit.js +14 -0
  623. package/test/sap/ui/core/qunit/bootstrap/ControlBehavior.qunit.js +110 -0
  624. package/test/sap/ui/core/qunit/bootstrap/PreloadCfg.qunit.js +4 -3
  625. package/test/sap/ui/core/qunit/bootstrap/ResourceRoot_ResourcesURL_Standard.qunit.html +1 -1
  626. package/test/sap/ui/core/qunit/bootstrap/ThemeVersion.beforeBootstrap.qunit.js +2 -3
  627. package/test/sap/ui/core/qunit/bootstrap/_checkCoreAndLibraryBooted.qunit.js +39 -34
  628. package/test/sap/ui/core/qunit/bootstrap/_checkCoreAndLibraryBooted_legacyAPIs.qunit.js +5 -1
  629. package/test/sap/ui/core/qunit/bootstrap/testsuite.bootstrap.qunit.js +51 -15
  630. package/test/sap/ui/core/qunit/compat_legacyAPIs/jquery-compat.qunit.html +23 -0
  631. package/test/sap/ui/core/qunit/compat_legacyAPIs/jquery-compat.qunit.js +1 -1
  632. package/test/sap/ui/core/qunit/compat_legacyAPIs/jquery.sap.stubs.qunit.js +16 -20
  633. package/test/sap/ui/core/qunit/compat_legacyAPIs/testsuite.compat.qunit.js +1 -4
  634. package/test/sap/ui/core/qunit/component/Component.qunit.js +74 -4
  635. package/test/sap/ui/core/qunit/component/Models.qunit.js +3 -1
  636. package/test/sap/ui/core/qunit/component/Preloading.qunit.js +8 -12
  637. package/test/sap/ui/core/qunit/component/UIComponent.qunit.js +8 -2
  638. package/test/sap/ui/core/qunit/component/testdata/routerPreloading/Component.js +23 -0
  639. package/test/sap/ui/core/qunit/component/testdata/routerPreloading/Main.view.xml +8 -0
  640. package/test/sap/ui/core/qunit/component/testdata/routerPreloading/manifest.json +34 -0
  641. package/test/sap/ui/core/qunit/component/testdata/targetsPreloading/Component.js +23 -0
  642. package/test/sap/ui/core/qunit/component/testdata/targetsPreloading/Main.view.xml +8 -0
  643. package/test/sap/ui/core/qunit/component/testdata/targetsPreloading/manifest.json +28 -0
  644. package/test/sap/ui/core/qunit/date/_Calendars.qunit.js +52 -0
  645. package/test/sap/ui/core/qunit/generic/legacy/ControlMemoryLeaks.qunit.js +18 -0
  646. package/test/sap/ui/core/qunit/generic/legacy/ControlMemoryLeaksUsingIterator.qunit.js +3 -4
  647. package/test/sap/ui/core/qunit/generic/legacy/DuplicateIdCheck.qunit.js +18 -0
  648. package/test/sap/ui/core/qunit/generic/legacy/SettersContextReturn.qunit.js +15 -0
  649. package/test/sap/ui/core/qunit/generic/testsuite.generic.qunit.js +21 -0
  650. package/test/sap/ui/core/qunit/gherkin/fixture/testHarnessAmbiguous.js +2 -3
  651. package/test/sap/ui/core/qunit/gherkin/fixture/testHarnessDuplicate.js +2 -3
  652. package/test/sap/ui/core/qunit/gherkin/fixture/testHarnessFailing.js +2 -3
  653. package/test/sap/ui/core/qunit/gherkin/opa5TestHarness.qunit.html +16 -0
  654. package/test/sap/ui/core/qunit/gherkin/opa5TestHarness.qunit.js +1 -1
  655. package/test/sap/ui/core/qunit/gherkin/qUnitTestHarness.qunit.html +16 -0
  656. package/test/sap/ui/core/qunit/gherkin/qUnitTestHarness.qunit.js +1 -1
  657. package/test/sap/ui/core/qunit/gherkin/testsuite.gherkin.qunit.js +3 -2
  658. package/test/sap/ui/core/qunit/i18n/Buddhist.qunit.js +3 -0
  659. package/test/sap/ui/core/qunit/i18n/GenericLocaleData.qunit.js +217 -114
  660. package/test/sap/ui/core/qunit/i18n/Islamic.qunit.js +3 -0
  661. package/test/sap/ui/core/qunit/i18n/Japanese.qunit.js +3 -0
  662. package/test/sap/ui/core/qunit/i18n/LocaleData.qunit.js +341 -7
  663. package/test/sap/ui/core/qunit/i18n/Persian.qunit.js +3 -0
  664. package/test/sap/ui/core/qunit/i18n/UniversalDate.qunit.js +3 -0
  665. package/test/sap/ui/core/qunit/i18n/UniversalDateUtils.qunit.js +10 -1
  666. package/test/sap/ui/core/qunit/i18n/helper/_timezones.js +17 -11
  667. package/test/sap/ui/core/qunit/i18n/testsuite.i18n.qunit.js +7 -1
  668. package/test/sap/ui/core/qunit/internal/1Ring.qunit.html +5 -1
  669. package/test/sap/ui/core/qunit/internal/1RingModels.qunit.html +2 -2
  670. package/test/sap/ui/core/qunit/internal/1RingModels.qunit.js +1 -0
  671. package/test/sap/ui/core/qunit/internal/AnnotationParser.qunit.html +1 -2
  672. package/test/sap/ui/core/qunit/internal/ODataV4.qunit.html +6 -1
  673. package/test/sap/ui/core/qunit/internal/testsuite.feature-odata-v4.qunit.js +2 -1
  674. package/test/sap/ui/core/qunit/jquery.sap.global-config.qunit.html +24 -0
  675. package/test/sap/ui/core/qunit/jquery.sap.global-config.qunit.js +12 -6
  676. package/test/sap/ui/core/qunit/jquery.sap.global-config_beforeBootstrap.qunit.js +1 -1
  677. package/test/sap/ui/core/qunit/json/JSONListBinding.qunit.js +30 -0
  678. package/test/sap/ui/core/qunit/loader/exposeAsAMDLoader.qunit.html +1 -0
  679. package/test/sap/ui/core/qunit/model/Binding.qunit.js +3 -0
  680. package/test/sap/ui/core/qunit/model/ClientListBinding.qunit.js +3 -0
  681. package/test/sap/ui/core/qunit/model/ClientPropertyBinding.qunit.js +3 -0
  682. package/test/sap/ui/core/qunit/model/ClientTreeBinding.qunit.js +3 -0
  683. package/test/sap/ui/core/qunit/model/ClientTreeBindingAdapter.qunit.js +6 -0
  684. package/test/sap/ui/core/qunit/model/CompositeDataState.qunit.js +3 -0
  685. package/test/sap/ui/core/qunit/model/Context.qunit.js +3 -0
  686. package/test/sap/ui/core/qunit/model/ContextBinding.qunit.js +3 -0
  687. package/test/sap/ui/core/qunit/model/Filter.qunit.js +49 -0
  688. package/test/sap/ui/core/qunit/model/FilterProcessor.qunit.js +40 -1
  689. package/test/sap/ui/core/qunit/model/ListBinding.qunit.js +23 -5
  690. package/test/sap/ui/core/qunit/model/Model.qunit.js +3 -0
  691. package/test/sap/ui/core/qunit/model/PropertyBinding.qunit.js +3 -0
  692. package/test/sap/ui/core/qunit/model/Sorter.qunit.js +3 -0
  693. package/test/sap/ui/core/qunit/model/TreeBinding.qunit.js +43 -3
  694. package/test/sap/ui/core/qunit/model/TreeBindingAdapter.qunit.js +3 -0
  695. package/test/sap/ui/core/qunit/mvc/Controller.qunit.js +107 -93
  696. package/test/sap/ui/core/qunit/mvc/View.qunit.js +3 -0
  697. package/test/sap/ui/core/qunit/mvc/XMLTemplateProcessor.qunit.js +17 -14
  698. package/test/sap/ui/core/qunit/mvc/XMLTemplateProcessorAsync.qunit.js +23 -12
  699. package/test/sap/ui/core/qunit/mvc/XMLTemplateProcessorRequireXML.qunit.js +29 -82
  700. package/test/sap/ui/core/qunit/mvc/XMLTemplateProcessorRequireXML_unavoidablySync.qunit.js +123 -0
  701. package/test/sap/ui/core/qunit/mvc/extensions/Controllerextensions.qunit.js +4 -0
  702. package/test/sap/ui/core/qunit/mvc/extensions/Controllerextensions_legacy.qunit.js +4 -0
  703. package/test/sap/ui/core/qunit/mvc/testsuite.mvc.qunit.js +16 -0
  704. package/test/sap/ui/core/qunit/mvc/viewprocessing/ViewProcessing.qunit.js +408 -419
  705. package/test/sap/ui/core/qunit/odata/AnnotationHelper.qunit.js +6 -4
  706. package/test/sap/ui/core/qunit/odata/ODataAnnotations.qunit.js +16 -0
  707. package/test/sap/ui/core/qunit/odata/ODataMetaModel.qunit.js +8 -1
  708. package/test/sap/ui/core/qunit/odata/ODataUtils.qunit.js +5 -1
  709. package/test/sap/ui/core/qunit/odata/type/DateTimeBase.qunit.js +4 -4
  710. package/test/sap/ui/core/qunit/odata/type/DateTimeWithTimezone.qunit.js +6 -6
  711. package/test/sap/ui/core/qunit/odata/type/Time.qunit.js +3 -4
  712. package/test/sap/ui/core/qunit/odata/type/TimeOfDay.qunit.js +4 -4
  713. package/test/sap/ui/core/qunit/odata/v2/ODataListBindingNoFakeService.qunit.js +36 -13
  714. package/test/sap/ui/core/qunit/odata/v2/ODataModel.integration.qunit.js +952 -292
  715. package/test/sap/ui/core/qunit/odata/v2/ODataModelNoFakeService.qunit.js +6 -4
  716. package/test/sap/ui/core/qunit/odata/v2/ODataPropertyBindingNoFakeService.qunit.js +6 -7
  717. package/test/sap/ui/core/qunit/odata/v2/ODataTreeBindingFlatNoFakeService.qunit.js +215 -1
  718. package/test/sap/ui/core/qunit/odata/v2/ODataTreeBindingNoFakeService.qunit.js +194 -3
  719. package/test/sap/ui/core/qunit/odata/v2/V2ODataModelDataState.qunit.js +3 -2
  720. package/test/sap/ui/core/qunit/odata/v4/Context.qunit.js +69 -2
  721. package/test/sap/ui/core/qunit/odata/v4/ODataListBinding.qunit.js +601 -99
  722. package/test/sap/ui/core/qunit/odata/v4/ODataModel.integration.qunit.js +1859 -407
  723. package/test/sap/ui/core/qunit/odata/v4/ODataModel.qunit.js +7 -5
  724. package/test/sap/ui/core/qunit/odata/v4/ODataModel.realOData.qunit.js +4 -4
  725. package/test/sap/ui/core/qunit/odata/v4/lib/_AggregationCache.qunit.js +909 -422
  726. package/test/sap/ui/core/qunit/odata/v4/lib/_AggregationHelper.qunit.js +21 -6
  727. package/test/sap/ui/core/qunit/odata/v4/lib/_Cache.qunit.js +104 -33
  728. package/test/sap/ui/core/qunit/odata/v4/lib/_Helper.qunit.js +8 -0
  729. package/test/sap/ui/core/qunit/odata/v4/lib/_MetadataRequestor.qunit.js +4 -4
  730. package/test/sap/ui/core/qunit/odata/v4/lib/_Requestor.qunit.js +9 -9
  731. package/test/sap/ui/core/qunit/odata/v4/lib/_V2MetadataConverter.qunit.js +3 -3
  732. package/test/sap/ui/core/qunit/odata/v4/lib/_V4MetadataConverter.qunit.js +3 -3
  733. package/test/sap/ui/core/qunit/opa/OpaPlugin.qunit.js +16 -0
  734. package/test/sap/ui/core/qunit/opa/_LogCollector.qunit.js +17 -9
  735. package/test/sap/ui/core/qunit/opa/actions/EnterText.qunit.js +51 -3
  736. package/test/sap/ui/core/qunit/opa/autowaiter/_cssAnimationWaiter.js +3 -3
  737. package/test/sap/ui/core/qunit/opa/autowaiter/_cssTransitionWaiter.js +3 -3
  738. package/test/sap/ui/core/qunit/opa/autowaiter/_jsAnimationWaiter.js +3 -3
  739. package/test/sap/ui/core/qunit/opa/autowaiter/_timeoutWaiter.js +11 -0
  740. package/test/sap/ui/core/qunit/opa/fixture/miniUI5Site.js +14 -8
  741. package/test/sap/ui/core/qunit/opa/fixture/uncaughtError.js +18 -12
  742. package/test/sap/ui/core/qunit/performance/BeaconRequest.qunit.js +18 -2
  743. package/test/sap/ui/core/qunit/resource/ResourceBinding.qunit.js +1 -0
  744. package/test/sap/ui/core/qunit/resource/ResourceModel.qunit.js +5 -4
  745. package/test/sap/ui/core/qunit/routing/async/Target.qunit.js +20 -18
  746. package/test/sap/ui/core/qunit/routing/async/Targets.qunit.js +1 -4
  747. package/test/sap/ui/core/qunit/routing/fixture/routingConfig/Component.js +2 -25
  748. package/test/sap/ui/core/qunit/routing/fixture/routingConfig/manifest.json +28 -0
  749. package/test/sap/ui/core/qunit/rule/misc/silentEventBus.qunit.js +1 -2
  750. package/test/sap/ui/core/qunit/testdata/libraries/scenario11/lib1/library.js +11 -0
  751. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib1/library-preload.js +3 -1
  752. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib1/library.js +3 -1
  753. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib2/library-preload.js +3 -1
  754. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib2/library.js +3 -1
  755. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib3/library-preload.js +2 -1
  756. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib3/library.js +2 -1
  757. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib5/library-preload.js +2 -1
  758. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib5/library.js +2 -1
  759. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib6/library-preload.js +2 -1
  760. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib6/library.js +2 -1
  761. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib8/library-preload.js +2 -1
  762. package/test/sap/ui/core/qunit/testdata/libraries/scenario14/lib8/library.js +2 -1
  763. package/test/sap/ui/core/qunit/testdata/libraries/terminologies/integration/lib/library-preload.js +1 -1
  764. package/test/sap/ui/core/qunit/testdata/shortcutHints/Component.js +9 -0
  765. package/test/sap/ui/core/qunit/testdata/shortcutHints/RootView.controller.js +8 -0
  766. package/test/sap/ui/core/qunit/testdata/shortcutHints/RootView.view.xml +16 -0
  767. package/test/sap/ui/core/qunit/testdata/shortcutHints/lib/MyControl.js +27 -0
  768. package/test/sap/ui/core/qunit/testdata/shortcutHints/manifest.json +26 -0
  769. package/test/sap/ui/core/qunit/testdata/uilib-custom-theme-fallback/library.js +4 -5
  770. package/test/sap/ui/core/qunit/testdata/uilib-failing-css-import/library.js +5 -6
  771. package/test/sap/ui/core/qunit/testdata/xml-require/view/XMLTemplateProcessorAsync_require_expression.controller.js +2 -1
  772. package/test/sap/ui/core/qunit/testdata/xml-require/view/XMLTemplateProcessorAsync_require_expression.view.xml +18 -1
  773. package/test/sap/ui/core/qunit/testsuite.core.framework.qunit.js +3 -0
  774. package/test/sap/ui/core/qunit/testsuites/testsuite.control.framework.qunit.js +0 -4
  775. package/test/sap/ui/core/qunit/testsuites/testsuite.foundation.enablement.qunit.js +6 -1
  776. package/test/sap/ui/core/qunit/testsuites/testsuite.managed.object.qunit.js +4 -1
  777. package/test/sap/ui/core/qunit/testsuites/testsuite.modular.core.qunit.js +1 -1
  778. package/test/sap/ui/core/qunit/testsuites/testsuite.security.qunit.js +3 -9
  779. package/test/sap/ui/core/qunit/types/DataType.qunit.js +14 -3
  780. package/test/sap/ui/core/qunit/types/Date.qunit.js +3 -0
  781. package/test/sap/ui/core/qunit/types/DateFormat.qunit.js +391 -147
  782. package/test/sap/ui/core/qunit/types/DateFormatTimezones.qunit.js +32 -29
  783. package/test/sap/ui/core/qunit/types/DateInterval.qunit.js +7 -4
  784. package/test/sap/ui/core/qunit/types/FileSizeFormat.qunit.js +5 -1
  785. package/test/sap/ui/core/qunit/types/ListFormat.qunit.js +3 -0
  786. package/test/sap/ui/core/qunit/types/NumberFormat.qunit.js +4 -3
  787. package/test/sap/ui/core/qunit/types/NumberFormatCurrencies.qunit.js +5 -4
  788. package/test/sap/ui/core/qunit/types/NumberFormatCurrenciesTrailing.qunit.js +4 -3
  789. package/test/sap/ui/core/qunit/types/SimpleType.qunit.js +3 -0
  790. package/test/sap/ui/core/qunit/types/TimezoneUtil.qunit.js +23 -0
  791. package/test/sap/ui/core/qunit/types/Types.qunit.js +44 -10
  792. package/test/sap/ui/core/qunit/types/testsuite.types.qunit.js +3 -0
  793. package/test/sap/ui/core/qunit/util/InvisibleMessage.qunit.js +4 -4
  794. package/test/sap/ui/core/qunit/util/XMLPreprocessor.qunit.js +592 -83
  795. package/test/sap/ui/core/qunit/util/beforeBootstrap/jQuery.sap.FrameOptions-allowlist.js +7 -0
  796. package/test/sap/ui/core/qunit/util/beforeBootstrap/jQuery.sap.FrameOptions-frameOptions.js +7 -0
  797. package/test/sap/ui/core/qunit/{bootstrap/CfgFromGlobalObject.qunit.html → util/jQuery.sap.FrameOptions-meta-tag-override-mode.qunit.html} +7 -11
  798. package/test/sap/ui/core/qunit/util/jQuery.sap.FrameOptions-meta-tag-override-mode.qunit.js +3 -4
  799. package/test/sap/ui/core/qunit/util/jQuery.sap.FrameOptions-meta-tag-override-service.qunit.html +26 -0
  800. package/test/sap/ui/core/qunit/util/jQuery.sap.FrameOptions-meta-tag-override-service.qunit.js +3 -4
  801. package/test/sap/ui/core/qunit/{bootstrap/CfgDefaults.qunit.html → util/jQuery.sap.FrameOptions-meta-tag.qunit.html} +5 -8
  802. package/test/sap/ui/core/qunit/util/jQuery.sap.FrameOptions-meta-tag.qunit.js +3 -4
  803. package/test/sap/ui/core/qunit/util/jQuery.sap.Version.qunit.js +10 -10
  804. package/test/sap/ui/core/qunit/util/jquery.sap.logger.qunit.html +18 -0
  805. package/test/sap/ui/core/qunit/util/jquery.sap.resources.qunit.js +1 -1
  806. package/test/sap/ui/core/qunit/util/testsuite.util.qunit.js +1 -3
  807. package/test/sap/ui/core/qunit/xml/XMLListBinding.qunit.js +3 -0
  808. package/test/sap/ui/core/qunit/xml/XMLModel.qunit.js +3 -0
  809. package/test/sap/ui/core/qunit/xml/XMLPropertyBinding.qunit.js +3 -0
  810. package/test/sap/ui/core/qunit/xml/XMLTreeBinding.qunit.js +3 -0
  811. package/test/sap/ui/core/relnotes/changes-1.119.json +1 -12
  812. package/test/sap/ui/core/relnotes/changes-1.120.json +360 -0
  813. package/test/sap/ui/core/terminologies/App.controller.js +2 -3
  814. package/test/sap/ui/core/terminologies/main.js +2 -3
  815. package/test/sap/ui/test/qunit/TestUtils.qunit.js +3 -3
  816. package/src/sap/ui/core/ConfigTest.js +0 -17
  817. package/src/sap/ui/core/_ConfigurationProvider.js +0 -187
  818. package/test/sap/ui/core/ComponentExtensibility_CustomizingDisabled.html +0 -57
  819. package/test/sap/ui/core/qunit/bootstrap/CfgDefaults.qunit.js +0 -71
  820. package/test/sap/ui/core/qunit/bootstrap/CfgFromConfigAttribute.qunit.html +0 -29
  821. package/test/sap/ui/core/qunit/bootstrap/CfgFromConfigAttribute.qunit.js +0 -40
  822. package/test/sap/ui/core/qunit/bootstrap/CfgFromGlobalObject.beforeBootstrap.qunit.js +0 -20
  823. package/test/sap/ui/core/qunit/bootstrap/CfgFromGlobalObject.qunit.js +0 -40
  824. package/test/sap/ui/core/qunit/bootstrap/CfgFromTagAttributes.qunit.html +0 -42
  825. package/test/sap/ui/core/qunit/bootstrap/CfgFromTagAttributes.qunit.js +0 -49
  826. package/test/sap/ui/core/qunit/util/BusyIndicatorNoCore.qunit.js +0 -96
  827. package/test/sap/ui/core/qunit/util/beforeBootstrap/jQuery.sap.FrameOptions-meta-tag.js +0 -10
  828. package/test/sap/ui/core/samples/mvc/JSONView.html +0 -65
@@ -2044,7 +2044,7 @@ sap.ui.define([
2044
2044
  return mNewQueryOptions === mQueryOptions;
2045
2045
  }), true);
2046
2046
  this.mock(oGroupLevelCache).expects("read")
2047
- .withExactArgs(1, 1, 0, "~oGroupLock~", "~fnDataRequested~")
2047
+ .withExactArgs(1, 1, 0, "~oGroupLock~", "~fnDataRequested~", true)
2048
2048
  .returns(SyncPromise.resolve({value : aReadResult}));
2049
2049
  this.mock(oCache).expects("addElements")
2050
2050
  .withExactArgs(sinon.match.same(aReadResult), 2, sinon.match.same(oGroupLevelCache), 1);
@@ -2053,6 +2053,50 @@ sap.ui.define([
2053
2053
  return oCache.readGap(oGroupLevelCache, 2, 3, "~oGroupLock~", "~fnDataRequested~");
2054
2054
  });
2055
2055
 
2056
+ //*********************************************************************************************
2057
+ QUnit.test("readGap: created persisted", function (assert) {
2058
+ const oCache
2059
+ = _AggregationCache.create(this.oRequestor, "~", "", {}, {hierarchyQualifier : "X"});
2060
+ oCache.aElements = [,, "~oStartElement~"];
2061
+ oCache.aElements.$byPredicate = {};
2062
+ const oHelperMock = this.mock(_Helper);
2063
+ oHelperMock.expects("getPrivateAnnotation")
2064
+ .withExactArgs("~oStartElement~", "index").returns(undefined); // created
2065
+ oHelperMock.expects("getPrivateAnnotation")
2066
+ .withExactArgs("~oStartElement~", "predicate").returns("~sPredicate~");
2067
+ const oGroupLevelCache = {refreshSingle : mustBeMocked};
2068
+ this.mock(oGroupLevelCache).expects("refreshSingle")
2069
+ .withExactArgs("~oGroupLock~", "", -1, "~sPredicate~", true, false, "~fnDataRequested~")
2070
+ .returns(SyncPromise.resolve(Promise.resolve("~oElement~")));
2071
+ oHelperMock.expects("copyPrivateAnnotation")
2072
+ .withExactArgs("~oStartElement~", "context", "~oElement~");
2073
+ this.mock(oCache).expects("addElements")
2074
+ .withExactArgs("~oElement~", 2, sinon.match.same(oGroupLevelCache));
2075
+
2076
+ // code under test
2077
+ const oResult = oCache.readGap(oGroupLevelCache, 2, 3, "~oGroupLock~", "~fnDataRequested~");
2078
+
2079
+ assert.strictEqual(oCache.aElements.$byPredicate["~sPredicate~"], oResult);
2080
+
2081
+ return oResult.then(function (vResult) {
2082
+ assert.strictEqual(vResult, undefined, "without a defined result");
2083
+ });
2084
+ });
2085
+
2086
+ //*********************************************************************************************
2087
+ QUnit.test("readGap: multiple created persisted", function (assert) {
2088
+ const oCache
2089
+ = _AggregationCache.create(this.oRequestor, "~", "", {}, {hierarchyQualifier : "X"});
2090
+ oCache.aElements = [,, "~oStartElement~"];
2091
+ this.mock(_Helper).expects("getPrivateAnnotation")
2092
+ .withExactArgs("~oStartElement~", "index").returns(undefined); // created
2093
+
2094
+ assert.throws(function () {
2095
+ // code under test
2096
+ oCache.readGap(/*oGroupLevelCache*/null, 2, 4, "~oGroupLock~", "~fnDataRequested~");
2097
+ }, new Error("Not just a single created persisted"));
2098
+ });
2099
+
2056
2100
  //*********************************************************************************************
2057
2101
  [
2058
2102
  "read: expand before read has finished",
@@ -2074,7 +2118,7 @@ sap.ui.define([
2074
2118
  _AggregationHelper.createPlaceholder(1, 2, oGroupLevelCache)];
2075
2119
 
2076
2120
  this.mock(oGroupLevelCache).expects("read")
2077
- .withExactArgs(1, 2, 0, "~oGroupLock~", "~fnDataRequested~")
2121
+ .withExactArgs(1, 2, 0, "~oGroupLock~", "~fnDataRequested~", true)
2078
2122
  .callsFake(function () {
2079
2123
  // while the read request is running - simulate an expand
2080
2124
  oCache.aElements.splice(1, 0, {/*oInsertedNode*/});
@@ -2114,7 +2158,7 @@ sap.ui.define([
2114
2158
  _AggregationHelper.createPlaceholder(1, 2, oGroupLevelCache)];
2115
2159
 
2116
2160
  this.mock(oGroupLevelCache).expects("read")
2117
- .withExactArgs(1, 2, 0, "~oGroupLock~", "~fnDataRequested~")
2161
+ .withExactArgs(1, 2, 0, "~oGroupLock~", "~fnDataRequested~", true)
2118
2162
  .callsFake(function () {
2119
2163
  return SyncPromise.resolve().then(function () {
2120
2164
  // while the read request is running - simulate a collapse
@@ -2159,7 +2203,7 @@ sap.ui.define([
2159
2203
  _Helper.setPrivateAnnotation(oCache.aElements[5], "predicate", "('B')");
2160
2204
 
2161
2205
  this.mock(oGroupLevelCache).expects("read")
2162
- .withExactArgs(3, 3, 0, "~oGroupLock~", "~fnDataRequested~").returns(oPromise);
2206
+ .withExactArgs(3, 3, 0, "~oGroupLock~", "~fnDataRequested~", true).returns(oPromise);
2163
2207
  this.mock(oCache).expects("addElements")
2164
2208
  .withExactArgs(sinon.match.same(oReadResult.value), 3,
2165
2209
  sinon.match.same(oGroupLevelCache), 3);
@@ -2168,9 +2212,13 @@ sap.ui.define([
2168
2212
  oResult = oCache.readGap(oGroupLevelCache, 3, 6, "~oGroupLock~", "~fnDataRequested~");
2169
2213
 
2170
2214
  assert.deepEqual(oCache.aElements.$byPredicate, bAsync ? {
2171
- "('A')" : oPromise,
2172
- "('B')" : oPromise
2215
+ "('A')" : SyncPromise.resolve(), // Note: not a strictEqual!
2216
+ "('B')" : SyncPromise.resolve()
2173
2217
  } : {});
2218
+ if (bAsync) {
2219
+ assert.strictEqual(oCache.aElements.$byPredicate["('A')"], oResult);
2220
+ assert.strictEqual(oCache.aElements.$byPredicate["('B')"], oResult);
2221
+ }
2174
2222
 
2175
2223
  return oResult;
2176
2224
  });
@@ -2457,15 +2505,32 @@ sap.ui.define([
2457
2505
  oGroupNode = {
2458
2506
  "@$ui5._" : {
2459
2507
  cache : oGroupLevelCache,
2508
+ index : 42,
2460
2509
  groupLevelCount : 7,
2461
2510
  spliced : [{
2462
- "@$ui5._" : {predicate : "('A')"},
2511
+ "@$ui5._" : {
2512
+ index : 23,
2513
+ parent : oCache.oFirstLevel, // unrealistic!
2514
+ predicate : "('A')"
2515
+ },
2463
2516
  "@$ui5.node.level" : 10
2464
2517
  }, {
2465
- "@$ui5._" : {placeholder : true, predicate : "n/a"},
2518
+ "@$ui5._" : {index : 24, placeholder : true, predicate : "n/a"},
2466
2519
  "@$ui5.node.level" : 11
2467
2520
  }, {
2468
- "@$ui5._" : {expanding : true, predicate : "('C')"},
2521
+ "@$ui5._" : {
2522
+ index : 25,
2523
+ expanding : true,
2524
+ parent : oCache.oFirstLevel, // unrealistic!
2525
+ predicate : "('C')"
2526
+ },
2527
+ "@$ui5.node.level" : 12
2528
+ }, {
2529
+ "@$ui5._" : {
2530
+ parent : oCache.oFirstLevel, // unrealistic!
2531
+ predicate : "('created')",
2532
+ transientPredicate : "($uid=1-23)"
2533
+ },
2469
2534
  "@$ui5.node.level" : 12
2470
2535
  }]
2471
2536
  },
@@ -2477,13 +2542,14 @@ sap.ui.define([
2477
2542
  oUpdateAllExpectation;
2478
2543
 
2479
2544
  oGroupNode["@$ui5._"].spliced[200000] = {
2480
- "@$ui5._" : {predicate : "('D')"},
2545
+ "@$ui5._" : {index : 200023, predicate : "('D')"},
2481
2546
  "@$ui5.node.level" : 10
2482
2547
  };
2483
2548
  aSpliced = oGroupNode["@$ui5._"].spliced.slice();
2484
2549
  if (bStale) {
2485
2550
  oGroupNode["@$ui5._"].spliced.$stale = true;
2486
2551
  }
2552
+ oGroupNode["@$ui5._"].spliced.$index = 12;
2487
2553
  aElements = [{}, oGroupNode, {}, {}];
2488
2554
  oCache.aElements = aElements.slice();
2489
2555
  oCache.aElements.$byPredicate = {};
@@ -2507,6 +2573,8 @@ sap.ui.define([
2507
2573
  .withExactArgs(sinon.match.same(aSpliced[0]), "('A')");
2508
2574
  oCacheMock.expects("turnIntoPlaceholder")
2509
2575
  .withExactArgs(sinon.match.same(aSpliced[2]), "('C')");
2576
+ oCacheMock.expects("turnIntoPlaceholder")
2577
+ .withExactArgs(sinon.match.same(aSpliced[3]), "('created')");
2510
2578
  oCacheMock.expects("turnIntoPlaceholder")
2511
2579
  .withExactArgs(sinon.match.same(aSpliced[200000]), "('D')");
2512
2580
  } else {
@@ -2527,17 +2595,23 @@ sap.ui.define([
2527
2595
 
2528
2596
  // check expanded nodes
2529
2597
  assert.deepEqual(Object.keys(oCache.aElements),
2530
- ["0", "1", "2", "3", "4", "200002", "200003", "200004", "$byPredicate", "$count"]);
2598
+ ["0", "1", "2", "3", "4", "5", "200002", "200003", "200004", "$byPredicate",
2599
+ "$count"]);
2531
2600
  assert.strictEqual(oCache.aElements[2], aSpliced[0]);
2532
2601
  assert.strictEqual(aSpliced[0]["@$ui5.node.level"], 6);
2602
+ assert.strictEqual(aSpliced[0]["@$ui5._"].index, 53);
2533
2603
  assert.strictEqual(oCache.aElements[3], aSpliced[1]);
2534
2604
  assert.strictEqual(aSpliced[1]["@$ui5.node.level"], 7);
2605
+ assert.strictEqual(aSpliced[1]["@$ui5._"].index, 24);
2535
2606
  assert.strictEqual(oCache.aElements[4], aSpliced[2]);
2536
2607
  assert.strictEqual(aSpliced[2]["@$ui5.node.level"], 8);
2608
+ assert.strictEqual(aSpliced[2]["@$ui5._"].index, 55);
2537
2609
  assert.strictEqual(_Helper.hasPrivateAnnotation(aSpliced[2], "expanding"), bStale,
2538
2610
  "deleted only if not stale");
2611
+ assert.notOk("index" in aSpliced[3]["@$ui5._"]);
2539
2612
  assert.strictEqual(oCache.aElements[200002], aSpliced[200000]);
2540
2613
  assert.strictEqual(aSpliced[200000]["@$ui5.node.level"], 6);
2614
+ assert.strictEqual(aSpliced[200000]["@$ui5._"].index, 200023);
2541
2615
 
2542
2616
  // check moved nodes
2543
2617
  assert.strictEqual(oCache.aElements[200003], aElements[2]);
@@ -2546,6 +2620,8 @@ sap.ui.define([
2546
2620
  assert.deepEqual(oCache.aElements.$byPredicate, bStale ? {} : {
2547
2621
  "('A')" : aSpliced[0],
2548
2622
  "('C')" : aSpliced[2],
2623
+ "('created')" : aSpliced[3],
2624
+ "($uid=1-23)" : aSpliced[3],
2549
2625
  "('D')" : aSpliced[200000]
2550
2626
  });
2551
2627
  });
@@ -2711,28 +2787,13 @@ sap.ui.define([
2711
2787
  //*********************************************************************************************
2712
2788
  [false, true].forEach(function (bUntilEnd) { // whether the collapsed children span until the end
2713
2789
  [undefined, false, true].forEach(function (bSubtotalsAtBottomOnly) {
2714
- [undefined, 5, 6].forEach(function (iExpandTo) {
2715
- var bSubtotalsAtBottom = bSubtotalsAtBottomOnly !== undefined,
2716
- sTitle = "collapse: until end = " + bUntilEnd
2717
- + ", subtotalsAtBottomOnly = " + bSubtotalsAtBottomOnly
2718
- + ", expandTo = " + iExpandTo;
2719
-
2720
- if (bSubtotalsAtBottom && iExpandTo) {
2721
- return;
2722
- }
2723
- if (!bUntilEnd && iExpandTo > 5) {
2724
- return; // w/ iExpandTo === 6, the collapsed children span until the end
2725
- }
2790
+ var bSubtotalsAtBottom = bSubtotalsAtBottomOnly !== undefined,
2791
+ sTitle = "collapse: until end = " + bUntilEnd
2792
+ + ", subtotalsAtBottomOnly = " + bSubtotalsAtBottomOnly;
2726
2793
 
2727
2794
  QUnit.test(sTitle, function (assert) {
2728
- var oAggregation = iExpandTo
2729
- ? {
2730
- expandTo : iExpandTo,
2795
+ var oAggregation = {
2731
2796
  hierarchyQualifier : "X"
2732
- } : { // filled before by buildApply
2733
- aggregate : {},
2734
- group : {},
2735
- groupLevels : ["group"]
2736
2797
  },
2737
2798
  oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, oAggregation),
2738
2799
  bCollapseBottom = bUntilEnd || bSubtotalsAtBottom, // whether bottom line is affected
@@ -2740,46 +2801,35 @@ sap.ui.define([
2740
2801
  "@$ui5.node.isExpanded" : false,
2741
2802
  A : "10" // placeholder for an aggregate with subtotals
2742
2803
  },
2743
- // eslint-disable-next-line no-nested-ternary
2744
- iDescendants = iExpandTo ? (iExpandTo > 5 ? 3 : 1) : undefined,
2745
2804
  aElements = [{
2746
2805
  // "@$ui5._" : {predicate : "('0')"},
2747
- // "@$ui5.node.level" : ignored
2748
2806
  }, {
2749
2807
  "@$ui5._" : {
2750
2808
  collapsed : oCollapsed,
2751
- descendants : iDescendants,
2809
+ index : "~index~",
2752
2810
  predicate : "('1')"
2753
- },
2754
- "@$ui5.node.isExpanded" : true,
2755
- "@$ui5.node.level" : 5
2811
+ }
2756
2812
  }, {
2757
- "@$ui5._" : {predicate : "('2')", transientPredicate : "($uid=1-23)"},
2758
- "@$ui5.node.level" : 6 // child
2813
+ "@$ui5._" : {predicate : "('2')", transientPredicate : "($uid=1-23)"}
2759
2814
  }, {
2760
- "@$ui5._" : {predicate : "('3')"},
2761
- "@$ui5.node.level" : iExpandTo ? 1 : 7 // placeholder for descendant, or grandchild
2815
+ "@$ui5._" : {predicate : "('3')"}
2762
2816
  }, {
2763
- "@$ui5._" : {predicate : "('4')"},
2817
+ "@$ui5._" : {predicate : "('4')"}
2764
2818
  // Note: for bSubtotalsAtBottom, this represents the extra row for subtotals
2765
- "@$ui5.node.level" : bUntilEnd ? 6 : 5 // child or sibling (or "uncle" etc.)
2766
2819
  }],
2767
2820
  aExpectedElements = [{
2768
2821
  // "@$ui5._" : {predicate : "('0')"},
2769
- // "@$ui5.node.level" : ignored
2770
2822
  }, {
2771
2823
  "@$ui5._" : {
2772
2824
  collapsed : oCollapsed,
2773
- descendants : iDescendants,
2825
+ index : "~index~",
2774
2826
  predicate : "('1')",
2775
2827
  spliced : [aElements[2], aElements[3], aElements[4]]
2776
2828
  },
2777
2829
  "@$ui5.node.isExpanded" : false,
2778
- "@$ui5.node.level" : 5,
2779
2830
  A : "10" // placeholder for an aggregate with subtotals
2780
2831
  }, {
2781
- "@$ui5._" : {predicate : "('4')"},
2782
- "@$ui5.node.level" : 5 // sibling
2832
+ "@$ui5._" : {predicate : "('4')"}
2783
2833
  }];
2784
2834
 
2785
2835
  if (bSubtotalsAtBottom) {
@@ -2805,6 +2855,8 @@ sap.ui.define([
2805
2855
  .withExactArgs(sinon.match.same(oCache.mChangeListeners), "~path~",
2806
2856
  sinon.match.same(aElements[1]), sinon.match.same(oCollapsed))
2807
2857
  .callThrough();
2858
+ this.mock(oCache).expects("countDescendants")
2859
+ .withExactArgs(sinon.match.same(aElements[1]), 1).returns(bUntilEnd ? 3 : 2);
2808
2860
 
2809
2861
  // code under test
2810
2862
  assert.strictEqual(oCache.collapse("~path~"), bCollapseBottom ? 3 : 2,
@@ -2829,188 +2881,97 @@ sap.ui.define([
2829
2881
  "('1')" : aElements[1],
2830
2882
  "('4')" : aElements[4]
2831
2883
  });
2884
+ assert.strictEqual(aElements[1]["@$ui5._"].spliced.$index, "~index~");
2832
2885
  });
2833
- });
2834
2886
  });
2835
2887
  });
2836
2888
 
2837
2889
  //*********************************************************************************************
2838
- QUnit.test("collapse: at end", function (assert) {
2839
- var oAggregation = { // filled before by buildApply
2840
- aggregate : {},
2841
- group : {},
2842
- groupLevels : ["group"]
2843
- },
2844
- oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, oAggregation),
2845
- oCollapsed = {"@$ui5.node.isExpanded" : false},
2846
- aElements = [{
2847
- "@$ui5.node.groupLevelCount" : 42,
2848
- "@$ui5.node.isExpanded" : true,
2849
- "@$ui5.node.level" : 5
2850
- }];
2851
-
2852
- oCache.aElements = aElements.slice(); // simulate a read
2853
- this.mock(oCache).expects("getValue").withExactArgs("~path~").returns(aElements[0]);
2854
- this.mock(_AggregationHelper).expects("getCollapsedObject")
2855
- .withExactArgs(sinon.match.same(aElements[0])).returns(oCollapsed);
2856
- this.mock(_Helper).expects("getPrivateAnnotation")
2857
- .withExactArgs(sinon.match.same(aElements[0]), "descendants").returns(undefined);
2858
- this.mock(_Helper).expects("updateAll")
2859
- .withExactArgs(sinon.match.same(oCache.mChangeListeners), "~path~",
2860
- sinon.match.same(aElements[0]), sinon.match.same(oCollapsed))
2861
- .callThrough();
2862
-
2863
- // code under test
2864
- assert.strictEqual(oCache.collapse("~path~"), 0, "number of removed elements");
2865
-
2866
- assert.deepEqual(oCache.aElements, [{
2867
- "@$ui5._" : {
2868
- spliced : []
2869
- },
2870
- "@$ui5.node.groupLevelCount" : 42,
2871
- "@$ui5.node.isExpanded" : false,
2890
+ QUnit.test("countDescendants: until end", function (assert) {
2891
+ const oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, {
2892
+ hierarchyQualifier : "X"
2893
+ });
2894
+ // Note: the collapsed children span until the end
2895
+ oCache.aElements = [{
2896
+ // "@$ui5.node.level" : ignored
2897
+ }, {
2898
+ "@$ui5.node.isExpanded" : true,
2872
2899
  "@$ui5.node.level" : 5
2873
- }]);
2874
- assert.strictEqual(oCache.aElements[0], aElements[0]);
2875
- });
2876
-
2877
- //*********************************************************************************************
2878
- [false, true].forEach(function (bExpanded) {
2879
- var sTitle = "collapse: skip descendants of manually collapsed node; isExpanded=" + bExpanded;
2880
-
2881
- QUnit.test(sTitle, function (assert) {
2882
- var oAggregation = {
2883
- expandTo : 3,
2884
- hierarchyQualifier : "X"
2885
- },
2886
- oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, oAggregation),
2887
- aElements = [{
2888
- "@$ui5._" : {
2889
- descendants : 41,
2890
- predicate : "('0')"
2891
- },
2892
- "@$ui5.node.isExpanded" : true,
2893
- "@$ui5.node.level" : 1
2894
- }, {
2895
- "@$ui5._" : {
2896
- descendants : 40,
2897
- predicate : "('1')"
2898
- },
2899
- "@$ui5.node.isExpanded" : bExpanded,
2900
- "@$ui5.node.level" : 2
2901
- }, {
2902
- "@$ui5._" : {
2903
- predicate : "('2')"
2904
- },
2905
- "@$ui5.node.level" : 1
2906
- }],
2907
- oPlaceholder,
2908
- aSpliced = [aElements[1]],
2909
- i;
2910
-
2911
- oCache.aElements = aElements.slice(); // simulate a read
2912
- oCache.aElements.$byPredicate = {
2913
- "('0')" : aElements[0],
2914
- "('1')" : aElements[1],
2915
- "('2')" : aElements[2]
2916
- };
2917
- if (bExpanded) {
2918
- for (i = 0; i < 40; i += 1) { // add 40 placeholders for descendants of ('1')
2919
- oPlaceholder = {"@$ui5.node.level" : 3};
2920
- oCache.aElements.splice(2, 0, oPlaceholder);
2921
- aSpliced.push(oPlaceholder);
2922
- }
2923
- }
2924
- this.mock(oCache).expects("getValue").withExactArgs("~path~").returns(aElements[0]);
2925
- // don't care about getCollapsedObject and updateAll here
2900
+ }, {
2901
+ "@$ui5.node.level" : 6 // child
2902
+ }, {
2903
+ "@$ui5.node.level" : 7 // grandchild
2904
+ }, {
2905
+ "@$ui5.node.level" : 6 // child
2906
+ }]; // simulate a read
2926
2907
 
2927
2908
  // code under test
2928
- assert.strictEqual(oCache.collapse("~path~"), bExpanded ? 41 : 1,
2909
+ assert.strictEqual(oCache.countDescendants(oCache.aElements[1], 1), 3,
2929
2910
  "number of removed elements");
2911
+ });
2930
2912
 
2931
- assert.deepEqual(oCache.aElements, [{
2913
+ //*********************************************************************************************
2914
+ QUnit.test("countDescendants: skip descendants of manually collapsed node", function (assert) {
2915
+ const oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, {
2916
+ expandTo : 3,
2917
+ hierarchyQualifier : "X"
2918
+ });
2919
+ oCache.aElements = [{
2932
2920
  "@$ui5._" : {
2933
2921
  descendants : 41,
2934
- predicate : "('0')",
2935
- spliced : aSpliced
2922
+ predicate : "('0')"
2936
2923
  },
2937
- "@$ui5.node.isExpanded" : false,
2924
+ "@$ui5.node.isExpanded" : true,
2938
2925
  "@$ui5.node.level" : 1
2926
+ }, {
2927
+ "@$ui5._" : {
2928
+ descendants : 40,
2929
+ predicate : "('1')"
2930
+ },
2931
+ "@$ui5.node.isExpanded" : true,
2932
+ "@$ui5.node.level" : 2
2939
2933
  }, {
2940
2934
  "@$ui5._" : {
2941
2935
  predicate : "('2')"
2942
2936
  },
2943
2937
  "@$ui5.node.level" : 1
2944
- }]);
2945
- assert.strictEqual(oCache.aElements[0], aElements[0]);
2946
- assert.strictEqual(oCache.aElements[1], aElements[2]);
2947
- });
2948
- });
2949
-
2950
- //*********************************************************************************************
2951
- QUnit.test("collapse: no descendants at edge of top pyramid", function (assert) {
2952
- var oAggregation = {
2953
- expandTo : 2,
2954
- hierarchyQualifier : "X"
2955
- },
2956
- oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, oAggregation),
2957
- aElements = [{
2958
- "@$ui5._" : {
2959
- descendants : 2,
2960
- predicate : "('0')"
2961
- },
2962
- "@$ui5.node.isExpanded" : true,
2963
- "@$ui5.node.level" : 1
2964
- }, {
2965
- "@$ui5._" : {
2966
- // no descendants at edge of top pyramid!
2967
- predicate : "('1')"
2968
- },
2969
- "@$ui5.node.isExpanded" : false,
2970
- "@$ui5.node.level" : 2
2971
- }, {
2972
- "@$ui5._" : {
2973
- // no descendants at edge of top pyramid!
2974
- predicate : "('2')"
2975
- },
2976
- "@$ui5.node.isExpanded" : false,
2977
- "@$ui5.node.level" : 2
2978
- }, {
2979
- "@$ui5._" : {
2980
- predicate : "('3')"
2981
- },
2982
- "@$ui5.node.level" : 1
2983
- }];
2984
-
2985
- oCache.aElements = aElements.slice(); // simulate a read
2986
- oCache.aElements.$byPredicate = {
2987
- "('0')" : aElements[0],
2988
- "('1')" : aElements[1],
2989
- "('2')" : aElements[2],
2990
- "('3')" : aElements[3]
2991
- };
2992
- this.mock(oCache).expects("getValue").withExactArgs("~path~").returns(aElements[0]);
2993
- // don't care about getCollapsedObject and updateAll here
2938
+ }]; // simulate a read
2939
+ for (let i = 0; i < 40; i += 1) { // add 40 placeholders for descendants of ('1')
2940
+ oCache.aElements.splice(2, 0, {"@$ui5.node.level" : 3});
2941
+ }
2994
2942
 
2995
2943
  // code under test
2996
- assert.strictEqual(oCache.collapse("~path~"), 2, "number of removed elements");
2944
+ assert.strictEqual(oCache.countDescendants(oCache.aElements[0], 0), 41,
2945
+ "number of removed elements");
2946
+ });
2997
2947
 
2998
- assert.deepEqual(oCache.aElements, [{
2948
+ //*********************************************************************************************
2949
+ QUnit.test("countDescendants: no descendants at edge of top pyramid", function (assert) {
2950
+ const oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, {
2951
+ expandTo : 2,
2952
+ hierarchyQualifier : "X"
2953
+ });
2954
+ oCache.aElements = [{
2999
2955
  "@$ui5._" : {
3000
- descendants : 2,
3001
- predicate : "('0')",
3002
- spliced : [aElements[1], aElements[2]]
2956
+ descendants : 2
3003
2957
  },
3004
- "@$ui5.node.isExpanded" : false,
2958
+ "@$ui5.node.isExpanded" : true,
3005
2959
  "@$ui5.node.level" : 1
3006
2960
  }, {
3007
- "@$ui5._" : {
3008
- predicate : "('3')"
3009
- },
2961
+ // no descendants at edge of top pyramid!
2962
+ "@$ui5.node.isExpanded" : false,
2963
+ "@$ui5.node.level" : 2
2964
+ }, {
2965
+ // no descendants at edge of top pyramid!
2966
+ "@$ui5.node.isExpanded" : false,
2967
+ "@$ui5.node.level" : 2
2968
+ }, {
3010
2969
  "@$ui5.node.level" : 1
3011
- }]);
3012
- assert.strictEqual(oCache.aElements[0], aElements[0]);
3013
- assert.strictEqual(oCache.aElements[1], aElements[3]);
2970
+ }]; // simulate a read
2971
+
2972
+ // code under test
2973
+ assert.strictEqual(oCache.countDescendants(oCache.aElements[0], 0), 2,
2974
+ "number of removed elements");
3014
2975
  });
3015
2976
 
3016
2977
  //*********************************************************************************************
@@ -3022,21 +2983,28 @@ sap.ui.define([
3022
2983
  $NodeProperty : "SomeNodeID" // unrealistic mix, but never mind
3023
2984
  },
3024
2985
  oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, oAggregation),
3025
- oPlaceholder = _AggregationHelper.createPlaceholder(NaN, 42, "~parent~"),
3026
- aElements = [{}, {}, oPlaceholder,, {}, {}],
2986
+ oPlaceholder42 = _AggregationHelper.createPlaceholder(NaN, 42, "~parent~"),
2987
+ oPlaceholder45 = _AggregationHelper.createPlaceholder(NaN, 45, "~parent~"),
2988
+ aElements = [{}, {}, oPlaceholder42,,, oPlaceholder45, {}, {}],
3027
2989
  aReadElements = [
3028
2990
  {"@$ui5._" : {predicate : "(1)"}},
3029
- {"@$ui5._" : {predicate : "(2)"}},
3030
- aElements[4]
2991
+ {"@$ui5._" : {predicate : "(2)", transientPredicate : "$uid=id-1-23"}},
2992
+ {"@$ui5._" : {predicate : "(3)"}},
2993
+ {"@$ui5._" : {predicate : "(4)"}},
2994
+ aElements[6]
3031
2995
  ];
3032
2996
 
3033
2997
  oCache.aElements = aElements.slice();
3034
2998
  oCache.aElements.$byPredicate = {
3035
2999
  "(2)" : SyncPromise.resolve() // SyncPromise may safely be overwritten
3036
3000
  };
3037
- this.mock(_AggregationHelper).expects("beforeOverwritePlaceholder")
3038
- .withExactArgs(sinon.match.same(oPlaceholder), sinon.match.same(aReadElements[0]),
3001
+ const oAggregationHelperMock = this.mock(_AggregationHelper);
3002
+ oAggregationHelperMock.expects("beforeOverwritePlaceholder")
3003
+ .withExactArgs(sinon.match.same(oPlaceholder42), sinon.match.same(aReadElements[0]),
3039
3004
  "~parent~", 42, "SomeNodeID");
3005
+ oAggregationHelperMock.expects("beforeOverwritePlaceholder")
3006
+ .withExactArgs(sinon.match.same(oPlaceholder45), sinon.match.same(aReadElements[3]),
3007
+ "~parent~", 44, "SomeNodeID");
3040
3008
  this.mock(_Helper).expects("updateNonExisting").never();
3041
3009
  this.mock(oCache).expects("hasPendingChangesForPath").never();
3042
3010
 
@@ -3047,18 +3015,67 @@ sap.ui.define([
3047
3015
  assert.strictEqual(oCache.aElements[1], aElements[1]);
3048
3016
  assert.strictEqual(oCache.aElements[2], aReadElements[0]);
3049
3017
  assert.strictEqual(oCache.aElements[3], aReadElements[1]);
3050
- assert.strictEqual(oCache.aElements[4], aElements[4]);
3051
- assert.strictEqual(oCache.aElements[5], aElements[5]);
3018
+ assert.strictEqual(oCache.aElements[4], aReadElements[2]);
3019
+ assert.strictEqual(oCache.aElements[5], aReadElements[3]);
3020
+ assert.strictEqual(oCache.aElements[6], aElements[6]);
3021
+ assert.strictEqual(oCache.aElements[7], aElements[7]);
3052
3022
  assert.deepEqual(oCache.aElements.$byPredicate, {
3053
3023
  "(1)" : aReadElements[0],
3054
- "(2)" : aReadElements[1]
3024
+ "(2)" : aReadElements[1],
3025
+ "$uid=id-1-23" : aReadElements[1],
3026
+ "(3)" : aReadElements[2],
3027
+ "(4)" : aReadElements[3]
3055
3028
  });
3056
3029
  assert.deepEqual(oCache.aElements, [
3057
3030
  {},
3058
3031
  {},
3059
3032
  {"@$ui5._" : {index : 42, parent : "~parent~", predicate : "(1)"}},
3060
- {"@$ui5._" : {index : 43, parent : "~parent~", predicate : "(2)"}},
3033
+ {"@$ui5._" // no index!
3034
+ : {parent : "~parent~", predicate : "(2)", transientPredicate : "$uid=id-1-23"}},
3035
+ {"@$ui5._" : {index : 43, parent : "~parent~", predicate : "(3)"}},
3036
+ {"@$ui5._" : {index : 44, parent : "~parent~", predicate : "(4)"}},
3037
+ {},
3038
+ {}
3039
+ ]);
3040
+ });
3041
+
3042
+ //*********************************************************************************************
3043
+ QUnit.test("addElements: no index for single created element", function (assert) {
3044
+ var oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, {
3045
+ hierarchyQualifier : "X",
3046
+ $NodeProperty : "SomeNodeID"
3047
+ }),
3048
+ oPlaceholder42 = _AggregationHelper.createPlaceholder(NaN, 42, "~parent~"),
3049
+ aElements = [{}, {}, oPlaceholder42, {}],
3050
+ oReadElement = {"@$ui5._" : {predicate : "(2)", transientPredicate : "$uid=id-1-23"}};
3051
+
3052
+ oCache.aElements = aElements.slice();
3053
+ oCache.aElements.$byPredicate = {
3054
+ "(2)" : SyncPromise.resolve() // SyncPromise may safely be overwritten
3055
+ };
3056
+ const oAggregationHelperMock = this.mock(_AggregationHelper);
3057
+ oAggregationHelperMock.expects("beforeOverwritePlaceholder")
3058
+ .withExactArgs(sinon.match.same(oPlaceholder42), sinon.match.same(oReadElement),
3059
+ "~parent~", undefined, "SomeNodeID");
3060
+ this.mock(_Helper).expects("updateNonExisting").never();
3061
+ this.mock(oCache).expects("hasPendingChangesForPath").never();
3062
+
3063
+ // code under test
3064
+ oCache.addElements(oReadElement, 2, "~parent~");
3065
+
3066
+ assert.strictEqual(oCache.aElements[0], aElements[0]);
3067
+ assert.strictEqual(oCache.aElements[1], aElements[1]);
3068
+ assert.strictEqual(oCache.aElements[2], oReadElement);
3069
+ assert.strictEqual(oCache.aElements[3], aElements[3]);
3070
+ assert.deepEqual(oCache.aElements.$byPredicate, {
3071
+ "(2)" : oReadElement,
3072
+ "$uid=id-1-23" : oReadElement
3073
+ });
3074
+ assert.deepEqual(oCache.aElements, [
3061
3075
  {},
3076
+ {},
3077
+ {"@$ui5._" // no index!
3078
+ : {parent : "~parent~", predicate : "(2)", transientPredicate : "$uid=id-1-23"}},
3062
3079
  {}
3063
3080
  ]);
3064
3081
  });
@@ -3086,7 +3103,6 @@ sap.ui.define([
3086
3103
  this.mock(_AggregationHelper).expects("beforeOverwritePlaceholder")
3087
3104
  .withExactArgs(sinon.match.same(oPlaceholder), sinon.match.same(oReadElement),
3088
3105
  sinon.match.same(oGroupLevelCache), 42, undefined);
3089
- this.mock(_Helper).expects("setPrivateAnnotation").exactly(bWithParentCache ? 2 : 0);
3090
3106
  this.mock(_Helper).expects("updateNonExisting").never();
3091
3107
  this.mock(oCache).expects("hasPendingChangesForPath").never();
3092
3108
 
@@ -3097,6 +3113,11 @@ sap.ui.define([
3097
3113
  assert.strictEqual(oCache.aElements[1], oReadElement);
3098
3114
  assert.strictEqual(oCache.aElements[2], aElements[2]);
3099
3115
  assert.deepEqual(oCache.aElements.$byPredicate, {"(1)" : oReadElement});
3116
+ assert.deepEqual(oReadElement, {
3117
+ "@$ui5._" : bWithParentCache
3118
+ ? {index : 42, parent : oGroupLevelCache, predicate : "(1)"}
3119
+ : {index : 42, predicate : "(1)"}
3120
+ });
3100
3121
  });
3101
3122
  });
3102
3123
 
@@ -3239,7 +3260,7 @@ sap.ui.define([
3239
3260
  },
3240
3261
  oCache = _AggregationCache.create(this.oRequestor, "Foo", "", {}, oAggregation),
3241
3262
  aElements = [{},, {}],
3242
- oElement = {"@$ui5._" : {transientPredicate : "$uid=id-1-23"}};
3263
+ oElement = {"@$ui5._" : {predicate : "(1)", transientPredicate : "$uid=id-1-23"}};
3243
3264
 
3244
3265
  oCache.aElements = aElements.slice();
3245
3266
  oCache.aElements.$byPredicate = {};
@@ -3254,11 +3275,16 @@ sap.ui.define([
3254
3275
  assert.strictEqual(oCache.aElements[1], oElement);
3255
3276
  assert.strictEqual(oCache.aElements[2], aElements[2]);
3256
3277
  assert.deepEqual(oCache.aElements.$byPredicate, {
3257
- "$uid=id-1-23" : oElement
3278
+ "$uid=id-1-23" : oElement,
3279
+ "(1)" : oElement
3258
3280
  });
3259
3281
  assert.deepEqual(oCache.aElements, [
3260
3282
  {},
3261
- {"@$ui5._" : {index : 42, parent : "~parent~", transientPredicate : "$uid=id-1-23"}},
3283
+ {"@$ui5._" : {
3284
+ parent : "~parent~",
3285
+ predicate : "(1)",
3286
+ transientPredicate : "$uid=id-1-23"
3287
+ }},
3262
3288
  {}
3263
3289
  ]);
3264
3290
  });
@@ -3280,6 +3306,53 @@ sap.ui.define([
3280
3306
  "~result~");
3281
3307
  });
3282
3308
 
3309
+ //*********************************************************************************************
3310
+ QUnit.test("getParentIndex", function (assert) {
3311
+ const oCache = _AggregationCache.create(this.oRequestor, "~", "", {},
3312
+ {hierarchyQualifier : "X"});
3313
+
3314
+ oCache.aElements[0] = {
3315
+ "@$ui5.node.level" : 0
3316
+ };
3317
+ oCache.aElements[1] = {
3318
+ "@$ui5.node.level" : 1
3319
+ };
3320
+ oCache.aElements[2] = {
3321
+ "@$ui5.node.level" : 2
3322
+ };
3323
+ oCache.aElements[3] = {
3324
+ "@$ui5.node.level" : 3
3325
+ };
3326
+ oCache.aElements[4] = {
3327
+ "@$ui5.node.level" : 2
3328
+ };
3329
+
3330
+ //code under test
3331
+ assert.strictEqual(oCache.getParentIndex(0), -1);
3332
+ assert.strictEqual(oCache.getParentIndex(1), -1);
3333
+ assert.strictEqual(oCache.getParentIndex(2), 1);
3334
+ assert.strictEqual(oCache.getParentIndex(3), 2);
3335
+ assert.strictEqual(oCache.getParentIndex(4), 1);
3336
+ });
3337
+
3338
+ //*********************************************************************************************
3339
+ QUnit.test("getParentIndex: error state", function (assert) {
3340
+ const oCache = _AggregationCache.create(this.oRequestor, "~", "", {},
3341
+ {hierarchyQualifier : "X"});
3342
+
3343
+ oCache.aElements[0] = {
3344
+ "@$ui5.node.level" : 3
3345
+ };
3346
+ oCache.aElements[1] = {
3347
+ "@$ui5.node.level" : 2
3348
+ };
3349
+
3350
+ assert.throws(function () {
3351
+ // code under test
3352
+ oCache.getParentIndex(1);
3353
+ }, new Error("Unexpected error"));
3354
+ });
3355
+
3283
3356
  //*********************************************************************************************
3284
3357
  [false, true].forEach(function (bCount) {
3285
3358
  [undefined, "~group~"].forEach(function (sGroupId) {
@@ -3625,6 +3698,7 @@ sap.ui.define([
3625
3698
  var oAggregation = {
3626
3699
  hierarchyQualifier : "X"
3627
3700
  },
3701
+ oAggregationHelperMock = this.mock(_AggregationHelper),
3628
3702
  oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, oAggregation),
3629
3703
  oHelperMock = this.mock(_Helper),
3630
3704
  oParentCache = {
@@ -3638,23 +3712,39 @@ sap.ui.define([
3638
3712
  };
3639
3713
 
3640
3714
  oHelperMock.expects("hasPrivateAnnotation")
3641
- .withExactArgs("~oElement~", "placeholder").returns(false);
3642
- oHelperMock.expects("setPrivateAnnotation").withExactArgs("~oElement~", "placeholder", 1);
3643
- this.mock(_AggregationHelper).expects("markSplicedStale").withExactArgs("~oElement~");
3644
- oHelperMock.expects("getPrivateAnnotation").withExactArgs("~oElement~", "parent")
3645
- .returns(oParentCache);
3646
- oHelperMock.expects("getPrivateAnnotation").withExactArgs("~oElement~", "index")
3715
+ .withExactArgs("~oElementB~", "placeholder").returns(false);
3716
+ oHelperMock.expects("setPrivateAnnotation").withExactArgs("~oElementB~", "placeholder", 1);
3717
+ oAggregationHelperMock.expects("markSplicedStale").withExactArgs("~oElementB~");
3718
+ oHelperMock.expects("getPrivateAnnotation").withExactArgs("~oElementB~", "index")
3647
3719
  .returns(42);
3648
- this.mock(oParentCache).expects("drop").withExactArgs(42, "('B')");
3720
+ oHelperMock.expects("getPrivateAnnotation").withExactArgs("~oElementB~", "parent")
3721
+ .returns(oParentCache);
3722
+ this.mock(oParentCache).expects("drop").withExactArgs(42, "('B')", true);
3649
3723
 
3650
3724
  // code under test
3651
- oCache.turnIntoPlaceholder("~oElement~", "('B')");
3725
+ oCache.turnIntoPlaceholder("~oElementB~", "('B')");
3652
3726
 
3653
3727
  assert.deepEqual(oCache.aElements.$byPredicate, {
3654
3728
  "('A')" : "~a~",
3655
3729
  "('C')" : "~c~"
3656
3730
  });
3657
3731
 
3732
+ oHelperMock.expects("hasPrivateAnnotation")
3733
+ .withExactArgs("~oElementC~", "placeholder").returns(false);
3734
+ oHelperMock.expects("setPrivateAnnotation").withExactArgs("~oElementC~", "placeholder", 1);
3735
+ oAggregationHelperMock.expects("markSplicedStale").withExactArgs("~oElementC~");
3736
+ oHelperMock.expects("getPrivateAnnotation").withExactArgs("~oElementC~", "index")
3737
+ .returns(undefined); // simulate a created element
3738
+ oHelperMock.expects("getPrivateAnnotation").withExactArgs("~oElementC~", "parent").never();
3739
+ // no drop!
3740
+
3741
+ // code under test
3742
+ oCache.turnIntoPlaceholder("~oElementC~", "('C')");
3743
+
3744
+ assert.deepEqual(oCache.aElements.$byPredicate, {
3745
+ "('A')" : "~a~"
3746
+ });
3747
+
3658
3748
  oCache.aElements = null; // do not touch ;-)
3659
3749
  // no other method calls expected!
3660
3750
  oHelperMock.expects("hasPrivateAnnotation")
@@ -3664,6 +3754,64 @@ sap.ui.define([
3664
3754
  oCache.turnIntoPlaceholder("~oElement~", "n/a");
3665
3755
  });
3666
3756
 
3757
+ //*********************************************************************************************
3758
+ QUnit.test("isAncestorOf: simple cases", function (assert) {
3759
+ const oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, {
3760
+ hierarchyQualifier : "X"
3761
+ });
3762
+ this.mock(oCache).expects("countDescendants").never();
3763
+
3764
+ // code under test
3765
+ assert.strictEqual(oCache.isAncestorOf(23, 23), true);
3766
+
3767
+ // code under test
3768
+ assert.strictEqual(oCache.isAncestorOf(42, 23), false);
3769
+
3770
+ oCache.aElements[17] = {"@$ui5.node.isExpanded" : false};
3771
+
3772
+ // code under test
3773
+ assert.strictEqual(oCache.isAncestorOf(17, 18), false);
3774
+
3775
+ oCache.aElements[18] = {
3776
+ "@$ui5.node.isExpanded" : true,
3777
+ "@$ui5.node.level" : 3
3778
+ };
3779
+ oCache.aElements[19] = {
3780
+ "@$ui5.node.level" : 3 // same level
3781
+ };
3782
+
3783
+ // code under test
3784
+ assert.strictEqual(oCache.isAncestorOf(18, 19), false);
3785
+
3786
+ oCache.aElements[20] = {
3787
+ "@$ui5.node.level" : 2 // lower level
3788
+ };
3789
+
3790
+ // code under test
3791
+ assert.strictEqual(oCache.isAncestorOf(18, 20), false);
3792
+ });
3793
+
3794
+ //*********************************************************************************************
3795
+ [-1, 0, +1].forEach((iDelta, i) => {
3796
+ QUnit.test("isAncestorOf: countDescendants #" + i, function (assert) {
3797
+ const oCache = _AggregationCache.create(this.oRequestor, "~", "", {}, {
3798
+ hierarchyQualifier : "X"
3799
+ });
3800
+ oCache.aElements[23] = {
3801
+ "@$ui5.node.isExpanded" : true,
3802
+ "@$ui5.node.level" : 3
3803
+ };
3804
+ oCache.aElements[42] = {
3805
+ "@$ui5.node.level" : 4
3806
+ };
3807
+ this.mock(oCache).expects("countDescendants")
3808
+ .withExactArgs(sinon.match.same(oCache.aElements[23]), 23).returns(42 - 23 + iDelta);
3809
+
3810
+ // code under test
3811
+ assert.strictEqual(oCache.isAncestorOf(23, 42), i > 0);
3812
+ });
3813
+ });
3814
+
3667
3815
  //*********************************************************************************************
3668
3816
  QUnit.test("keepOnlyGivenElements: empty", function (assert) {
3669
3817
  var oAggregation = {
@@ -3688,6 +3836,8 @@ sap.ui.define([
3688
3836
  "@$ui5._" : {predicate : "('B')"}
3689
3837
  }, {
3690
3838
  "@$ui5._" : {predicate : "('C')"}
3839
+ }, {
3840
+ "@$ui5._" : {transientPredicate : "($uid=1-23)"} // must be ignored
3691
3841
  }],
3692
3842
  aResult;
3693
3843
 
@@ -3710,132 +3860,173 @@ sap.ui.define([
3710
3860
  //*********************************************************************************************
3711
3861
  [false, true].forEach((bTransient) => {
3712
3862
  [0, 1].forEach((iOldSiblingCount) => {
3713
- [false, true].forEach((bParentHasCache) => {
3714
- const sTitle = `move: already transient = ${bTransient},
3715
- old sibling count = ${iOldSiblingCount}, new parent already has cache = ${bParentHasCache}`;
3863
+ [false, true].forEach((bParentIsLeaf) => {
3864
+ [false, true].forEach((bSpliced) => {
3865
+ const sTitle = `move: already transient = ${bTransient},
3866
+ old sibling count = ${iOldSiblingCount}, new parent is leaf = ${bParentIsLeaf},
3867
+ new parent was expanded before = ${bSpliced}`;
3716
3868
 
3717
- QUnit.test(sTitle, function (assert) {
3718
- const oCache = _AggregationCache.create(this.oRequestor, "n/a", "", {}, {
3869
+ if (bParentIsLeaf && bSpliced) {
3870
+ return;
3871
+ }
3872
+
3873
+ QUnit.test(sTitle, function (assert) {
3874
+ const oHelperMock = this.mock(_Helper);
3875
+ oHelperMock.expects("uid").withExactArgs().returns("1-23");
3876
+ const oCache = _AggregationCache.create(this.oRequestor, "n/a", "", {}, {
3719
3877
  $ParentNavigationProperty : "myParent",
3720
3878
  hierarchyQualifier : "X"
3721
3879
  });
3722
- const oOldParent = {"@$ui5.node.isExpanded" : "n/a"};
3723
- const oParentNode = {"@$ui5.node.level" : 9};
3724
- oCache.aElements = ["a", oOldParent, "~oChildNode~", "d", "e", "f", "g", oParentNode, "i"];
3880
+ oCache.iReadLength = "~iReadLength~";
3881
+ const oChildNode = {ID : "child"};
3882
+ const oParentNode = {"@$ui5.node.level" : 9, ID : "parent"};
3883
+ if (!bParentIsLeaf) {
3884
+ oParentNode["@$ui5.node.isExpanded"] = false;
3885
+ }
3886
+ oCache.aElements = ["a", "~oOldParent~", oChildNode, "d", "e", "f", "g", oParentNode, "i"];
3725
3887
  oCache.aElements.$byPredicate = {
3726
- "('23')" : "~oChildNode~",
3888
+ "('23')" : oChildNode,
3727
3889
  "('42')" : oParentNode
3728
3890
  };
3891
+ oCache.aElements.$count = 100;
3892
+ const oParentCache = {
3893
+ read : mustBeMocked,
3894
+ restoreElement : mustBeMocked,
3895
+ setEmpty : mustBeMocked
3896
+ };
3897
+ oHelperMock.expects("getPrivateAnnotation")
3898
+ .withExactArgs(sinon.match.same(oParentNode), "cache")
3899
+ .returns(bParentIsLeaf || !bSpliced ? undefined : oParentCache);
3900
+ this.mock(oCache).expects("createGroupLevelCache")
3901
+ .exactly(bParentIsLeaf || !bSpliced ? 1 : 0)
3902
+ .withExactArgs(sinon.match.same(oParentNode)).returns(oParentCache);
3903
+ const oGroupLock = {
3904
+ getUnlockedCopy : mustBeMocked
3905
+ };
3906
+ if (!bParentIsLeaf && !bSpliced) {
3907
+ this.mock(oParentCache).expects("restoreElement")
3908
+ .withExactArgs(undefined, 0, sinon.match.same(oChildNode), "", undefined,
3909
+ "($uid=1-23)");
3910
+ this.mock(oGroupLock).expects("getUnlockedCopy").withExactArgs()
3911
+ .returns("~unlockedCopy~");
3912
+ this.mock(oParentCache).expects("read")
3913
+ .withExactArgs(0, "~iReadLength~", 0, "~unlockedCopy~")
3914
+ .returns(SyncPromise.resolve());
3915
+ }
3729
3916
  const oRequestExpectation = this.mock(this.oRequestor).expects("request")
3730
- .withExactArgs("PATCH", "Foo('23')", "~oGroupLock~", {
3731
- "If-Match" : "~oChildNode~",
3917
+ .withExactArgs("PATCH", "Foo('23')", sinon.match.same(oGroupLock), {
3918
+ "If-Match" : oChildNode,
3732
3919
  Prefer : "return=minimal"
3733
3920
  }, {"myParent@odata.bind" : "Foo('42')"},
3734
3921
  /*fnSubmit*/null, /*fnCancel*/sinon.match.func)
3735
3922
  .resolves({"@odata.etag" : "etag"});
3736
- const oHelperMock = this.mock(_Helper);
3737
3923
  oHelperMock.expects("updateExisting")
3738
- .withExactArgs(sinon.match.same(oCache.mChangeListeners), "('23')", "~oChildNode~",
3739
- {"@odata.etag" : "etag"});
3740
- const oCacheMock = this.mock(oCache);
3741
- oCacheMock.expects("shiftIndex").withExactArgs(2, -1).callsFake(function () {
3742
- assert.deepEqual(oCache.aElements,
3743
- ["a", oOldParent, "~oChildNode~", "d", "e", "f", "g", oParentNode, "i"]);
3744
- });
3924
+ .withExactArgs(sinon.match.same(oCache.mChangeListeners), "('23')",
3925
+ sinon.match.same(oChildNode), {"@odata.etag" : "etag", "@$ui5.node.level" : 10});
3745
3926
  const oOldParentCache = {
3746
3927
  getValue : mustBeMocked,
3747
3928
  removeElement : mustBeMocked,
3748
3929
  setActive : mustBeMocked
3749
3930
  };
3750
- oHelperMock.expects("getPrivateAnnotation").withExactArgs("~oChildNode~", "parent")
3751
- .returns(oOldParentCache);
3752
- oHelperMock.expects("getPrivateAnnotation").withExactArgs("~oChildNode~", "index")
3753
- .returns("~index~");
3754
- this.mock(oOldParentCache).expects("removeElement")
3755
- .withExactArgs(undefined, "~index~", "('23')", "");
3931
+ oHelperMock.expects("getPrivateAnnotation")
3932
+ .withExactArgs(sinon.match.same(oChildNode), "parent").returns(oOldParentCache);
3933
+ oHelperMock.expects("getPrivateAnnotation")
3934
+ .withExactArgs(sinon.match.same(oChildNode), "index", 0).returns("~index~");
3935
+ this.mock(oOldParentCache).expects("removeElement").withExactArgs("~index~", "('23')");
3756
3936
  this.mock(oOldParentCache).expects("getValue").withExactArgs("$count")
3757
3937
  .returns(iOldSiblingCount);
3758
- oHelperMock.expects("getPrivateAnnotation").exactly(iOldSiblingCount ? 0 : 1)
3759
- .withExactArgs(sinon.match.same(oOldParent), "predicate").returns("('b')");
3760
- oHelperMock.expects("updateAll").exactly(iOldSiblingCount ? 0 : 1)
3761
- .withExactArgs(sinon.match.same(oCache.mChangeListeners), "('b')",
3762
- sinon.match.same(oOldParent), {"@$ui5.node.isExpanded" : undefined});
3938
+ this.mock(oCache).expects("makeLeaf").exactly(iOldSiblingCount ? 0 : 1)
3939
+ .withExactArgs("~oOldParent~");
3763
3940
  oHelperMock.expects("deletePrivateAnnotation").exactly(iOldSiblingCount ? 0 : 1)
3764
- .withExactArgs(sinon.match.same(oOldParent), "cache");
3941
+ .withExactArgs("~oOldParent~", "cache");
3765
3942
  this.mock(oOldParentCache).expects("setActive").exactly(iOldSiblingCount ? 0 : 1)
3766
3943
  .withExactArgs(false);
3944
+ oHelperMock.expects("deletePrivateAnnotation")
3945
+ .withExactArgs(sinon.match.same(oChildNode), "index");
3767
3946
  oHelperMock.expects("hasPrivateAnnotation")
3768
- .withExactArgs("~oChildNode~", "transientPredicate").returns(bTransient);
3769
- oHelperMock.expects("uid").exactly(bTransient ? 0 : 1).withExactArgs().returns("1-23");
3947
+ .withExactArgs(sinon.match.same(oChildNode), "transientPredicate").returns(bTransient);
3770
3948
  oHelperMock.expects("setPrivateAnnotation").exactly(bTransient ? 0 : 1)
3771
- .withExactArgs("~oChildNode~", "transientPredicate", "($uid=1-23)");
3949
+ .withExactArgs(sinon.match.same(oChildNode), "transientPredicate", "($uid=1-23)");
3772
3950
  oHelperMock.expects("updateAll").exactly(bTransient ? 0 : 1)
3773
- .withExactArgs(sinon.match.same(oCache.mChangeListeners), "('23')", "~oChildNode~",
3774
- {"@$ui5.context.isTransient" : false});
3775
- const oParentCache = {
3776
- restoreElement : mustBeMocked,
3777
- setEmpty : mustBeMocked
3778
- };
3779
- oHelperMock.expects("getPrivateAnnotation")
3780
- .withExactArgs(sinon.match.same(oParentNode), "cache")
3781
- .returns(bParentHasCache ? oParentCache : undefined);
3782
- oCacheMock.expects("createGroupLevelCache").exactly(bParentHasCache ? 0 : 1)
3783
- .withExactArgs(sinon.match.same(oParentNode)).returns(oParentCache);
3784
- this.mock(oParentCache).expects("setEmpty").exactly(bParentHasCache ? 0 : 1)
3951
+ .withExactArgs(sinon.match.same(oCache.mChangeListeners), "('23')",
3952
+ sinon.match.same(oChildNode), {"@$ui5.context.isTransient" : false});
3953
+ this.mock(oCache).expects("shiftIndex").exactly(bTransient ? 0 : 1)
3954
+ .withExactArgs(2, -1).callsFake(function () {
3955
+ assert.deepEqual(oCache.aElements,
3956
+ ["a", "~oOldParent~", oChildNode, "d", "e", "f", "g", oParentNode, "i"]);
3957
+ });
3958
+ this.mock(oParentCache).expects("setEmpty").exactly(bParentIsLeaf ? 1 : 0)
3785
3959
  .withExactArgs();
3786
- oHelperMock.expects("setPrivateAnnotation").exactly(bParentHasCache ? 0 : 1)
3960
+ const oCacheExpectation = oHelperMock.expects("setPrivateAnnotation")
3961
+ .exactly(bParentIsLeaf || !bSpliced ? 1 : 0)
3787
3962
  .withExactArgs(sinon.match.same(oParentNode), "cache", sinon.match.same(oParentCache));
3788
- oHelperMock.expects("updateAll").exactly(bParentHasCache ? 0 : 1)
3963
+ oHelperMock.expects("updateAll").exactly(bParentIsLeaf ? 1 : 0)
3789
3964
  .withExactArgs(sinon.match.same(oCache.mChangeListeners), "('42')",
3790
3965
  sinon.match.same(oParentNode), {"@$ui5.node.isExpanded" : true});
3791
- this.mock(oParentCache).expects("restoreElement")
3792
- .withExactArgs(undefined, 0, "~oChildNode~", "");
3793
- oHelperMock.expects("setPrivateAnnotation").withExactArgs("~oChildNode~", "index", 0);
3794
3966
  const oParentExpectation = oHelperMock.expects("setPrivateAnnotation")
3795
- .withExactArgs("~oChildNode~", "parent", sinon.match.same(oParentCache));
3796
- const oNodeLevelExpectation = oHelperMock.expects("updateAll")
3797
- .withExactArgs(sinon.match.same(oCache.mChangeListeners), "('23')", "~oChildNode~",
3798
- {"@$ui5.node.level" : 10});
3799
- oCacheMock.expects("shiftIndex").withExactArgs(7, +1).callsFake(function () {
3800
- assert.deepEqual(oCache.aElements,
3801
- ["a", oOldParent, "d", "e", "f", "g", oParentNode, "~oChildNode~", "i"]);
3802
- // 'relies on "parent" & "@$ui5.node.level"!'
3803
- assert.strictEqual(oParentExpectation.callCount, 1);
3804
- assert.strictEqual(oNodeLevelExpectation.callCount, 1);
3967
+ .withExactArgs(sinon.match.same(oChildNode), "parent", sinon.match.same(oParentCache));
3968
+ if (bParentIsLeaf || bSpliced) {
3969
+ this.mock(oParentCache).expects("restoreElement")
3970
+ .withExactArgs(undefined, 0, sinon.match.same(oChildNode), "");
3971
+ }
3972
+ const aSpliced = bSpliced ? [{"@$ui5.node.level" : 7}, "X", "Y", "Z"] : undefined;
3973
+ oHelperMock.expects("getPrivateAnnotation").exactly(bParentIsLeaf || bSpliced ? 1 : 0)
3974
+ .withExactArgs(sinon.match.same(oParentNode), "spliced").returns(aSpliced);
3975
+ this.mock(oCache).expects("expand").exactly(!bParentIsLeaf ? 1 : 0)
3976
+ .withExactArgs(sinon.match.same(_GroupLock.$cached), "('42')")
3977
+ .callsFake(function () {
3978
+ if (bSpliced) {
3979
+ assert.strictEqual(oChildNode["@$ui5.node.level"], 7);
3980
+ assert.deepEqual(aSpliced,
3981
+ [oChildNode, {"@$ui5.node.level" : 7}, "X", "Y", "Z"]);
3982
+ } else {
3983
+ assert.deepEqual(oChildNode, {ID : "child"}, "unchanged");
3984
+ assert.ok(oCacheExpectation.calledOnce);
3985
+ }
3986
+ assert.strictEqual(oCache.aElements.$count, 99);
3987
+ assert.ok(oParentExpectation.calledOnce);
3988
+ return SyncPromise.resolve("~iResult~");
3805
3989
  });
3806
3990
 
3807
3991
  // code under test
3808
- return oCache.move("~oGroupLock~", "Foo('23')", "Foo('42')")
3809
- .then(function (vResult) {
3810
- assert.strictEqual(vResult, undefined, "without a defined result");
3811
- assert.deepEqual(oCache.aElements,
3812
- ["a", oOldParent, "d", "e", "f", "g", oParentNode, "~oChildNode~", "i"]);
3992
+ const oSyncPromise = oCache.move(oGroupLock, "Foo('23')", "Foo('42')");
3993
+
3994
+ assert.strictEqual(oSyncPromise.isPending(), true);
3995
+
3996
+ return oSyncPromise.then(function (iResult) {
3997
+ assert.strictEqual(iResult, !bParentIsLeaf ? "~iResult~" : 1);
3998
+ assert.deepEqual(oCache.aElements, bParentIsLeaf
3999
+ ? ["a", "~oOldParent~", "d", "e", "f", "g", oParentNode, oChildNode, "i"]
4000
+ : ["a", "~oOldParent~", "d", "e", "f", "g", oParentNode, "i"]);
3813
4001
  assert.deepEqual(oCache.aElements.$byPredicate, bTransient ? {
3814
- "('23')" : "~oChildNode~",
4002
+ "('23')" : oChildNode,
3815
4003
  "('42')" : oParentNode
3816
4004
  } : {
3817
- "($uid=1-23)" : "~oChildNode~",
3818
- "('23')" : "~oChildNode~",
4005
+ "($uid=1-23)" : oChildNode,
4006
+ "('23')" : oChildNode,
3819
4007
  "('42')" : oParentNode
3820
4008
  });
3821
- assert.deepEqual(oOldParent,
3822
- iOldSiblingCount ? {"@$ui5.node.isExpanded" : "n/a"} : {});
4009
+ assert.strictEqual(oCache.aElements.$count, !bParentIsLeaf ? 99 : 100);
3823
4010
 
3824
4011
  // code under test (invoke fnCancel which does nothing)
3825
4012
  oRequestExpectation.args[0][6]();
3826
4013
  });
3827
4014
  });
4015
+ });
3828
4016
  });
3829
4017
  });
3830
4018
  });
3831
4019
 
3832
4020
  //*********************************************************************************************
3833
- QUnit.test("move: failure", function (assert) {
4021
+ QUnit.test("move: PATCH failure", function (assert) {
3834
4022
  const oCache = _AggregationCache.create(this.oRequestor, "n/a", "", {}, {
3835
4023
  $ParentNavigationProperty : "myParent",
3836
4024
  hierarchyQualifier : "X"
3837
4025
  });
3838
4026
  oCache.aElements.$byPredicate["('23')"] = "~oChildNode~";
4027
+ oCache.aElements.$byPredicate["('42')"] = "~oParentNode~";
4028
+ this.mock(_Helper).expects("getPrivateAnnotation").withExactArgs("~oParentNode~", "cache")
4029
+ .returns("n/a");
3839
4030
  const oError = new Error("This call intentionally failed");
3840
4031
  this.mock(this.oRequestor).expects("request")
3841
4032
  .withExactArgs("PATCH", "Foo('23')", "~oGroupLock~", {
@@ -3846,8 +4037,59 @@ sap.ui.define([
3846
4037
  .rejects(oError);
3847
4038
 
3848
4039
  // code under test
3849
- return oCache.move("~oGroupLock~", "Foo('23')", "Foo('42')")
3850
- .then(function () {
4040
+ const oSyncPromise = oCache.move("~oGroupLock~", "Foo('23')", "Foo('42')");
4041
+
4042
+ assert.strictEqual(oSyncPromise.isPending(), true);
4043
+
4044
+ return oSyncPromise.then(function () {
4045
+ assert.ok(false, "unexpected success");
4046
+ }, function (oError0) {
4047
+ assert.strictEqual(oError0, oError);
4048
+ });
4049
+ });
4050
+
4051
+ //*********************************************************************************************
4052
+ QUnit.test("move: GET failure", function (assert) {
4053
+ const oCache = _AggregationCache.create(this.oRequestor, "n/a", "", {}, {
4054
+ $ParentNavigationProperty : "myParent",
4055
+ hierarchyQualifier : "X"
4056
+ });
4057
+ oCache.iReadLength = "~iReadLength~";
4058
+ oCache.aElements.$byPredicate["('23')"] = "~oChildNode~";
4059
+ const oParentNode = {"@$ui5.node.isExpanded" : false};
4060
+ oCache.aElements.$byPredicate["('42')"] = oParentNode;
4061
+ const oParentCache = {
4062
+ read : mustBeMocked,
4063
+ restoreElement : mustBeMocked,
4064
+ setEmpty : mustBeMocked
4065
+ };
4066
+ this.mock(oCache).expects("createGroupLevelCache")
4067
+ .withExactArgs(sinon.match.same(oParentNode)).returns(oParentCache);
4068
+ this.mock(_Helper).expects("uid").withExactArgs().returns("1-23");
4069
+ this.mock(oParentCache).expects("restoreElement")
4070
+ .withExactArgs(undefined, 0, "~oChildNode~", "", undefined, "($uid=1-23)");
4071
+ const oGroupLock = {
4072
+ getUnlockedCopy : mustBeMocked
4073
+ };
4074
+ this.mock(oGroupLock).expects("getUnlockedCopy").withExactArgs().returns("~unlockedCopy~");
4075
+ const oError = new Error("This call intentionally failed");
4076
+ this.mock(oParentCache).expects("read")
4077
+ .withExactArgs(0, "~iReadLength~", 0, "~unlockedCopy~")
4078
+ .returns(SyncPromise.resolve(Promise.reject(oError)));
4079
+ this.mock(this.oRequestor).expects("request")
4080
+ .withExactArgs("PATCH", "Foo('23')", sinon.match.same(oGroupLock), {
4081
+ "If-Match" : "~oChildNode~",
4082
+ Prefer : "return=minimal"
4083
+ }, {"myParent@odata.bind" : "Foo('42')"},
4084
+ /*fnSubmit*/null, /*fnCancel*/sinon.match.func)
4085
+ .resolves();
4086
+
4087
+ // code under test
4088
+ const oSyncPromise = oCache.move(oGroupLock, "Foo('23')", "Foo('42')");
4089
+
4090
+ assert.strictEqual(oSyncPromise.isPending(), true);
4091
+
4092
+ return oSyncPromise.then(function () {
3851
4093
  assert.ok(false, "unexpected success");
3852
4094
  }, function (oError0) {
3853
4095
  assert.strictEqual(oError0, oError);
@@ -3856,11 +4098,20 @@ sap.ui.define([
3856
4098
 
3857
4099
  //*********************************************************************************************
3858
4100
  [false, true].forEach(function (bHasGroupLevelCache) {
3859
- QUnit.test("create: already has group level cache: " + bHasGroupLevelCache, function (assert) {
4101
+ [false, true].forEach(function (bInFirstLevel) {
4102
+ var sTitle = "create: already has group level cache: " + bHasGroupLevelCache
4103
+ + ", create inside oFirstLevel: " + bInFirstLevel;
4104
+
4105
+ if (bHasGroupLevelCache && bInFirstLevel) {
4106
+ return;
4107
+ }
4108
+
4109
+ QUnit.test(sTitle, function (assert) {
3860
4110
  var fnCancelCallback;
3861
4111
 
3862
4112
  const oCache = _AggregationCache.create(this.oRequestor, "Foo", "", {}, {
3863
4113
  $ParentNavigationProperty : "myParent",
4114
+ expandTo : bInFirstLevel ? 25 : /*test defaulting!*/undefined,
3864
4115
  hierarchyQualifier : "X"
3865
4116
  });
3866
4117
  const oGroupLevelCache = {
@@ -3875,11 +4126,14 @@ sap.ui.define([
3875
4126
  oCache.aElements.$byPredicate = {"('42')" : oParentNode};
3876
4127
  oCache.aElements.$count = 5;
3877
4128
  const oCacheMock = this.mock(oCache);
3878
- oCacheMock.expects("createGroupLevelCache").exactly(bHasGroupLevelCache ? 0 : 1)
4129
+ oCacheMock.expects("createGroupLevelCache")
4130
+ .exactly(bHasGroupLevelCache || bInFirstLevel ? 0 : 1)
3879
4131
  .withExactArgs(sinon.match.same(oParentNode)).returns(oGroupLevelCache);
3880
- this.mock(oGroupLevelCache).expects("setEmpty").exactly(bHasGroupLevelCache ? 0 : 1)
4132
+ this.mock(oGroupLevelCache).expects("setEmpty")
4133
+ .exactly(bHasGroupLevelCache || bInFirstLevel ? 0 : 1)
3881
4134
  .withExactArgs();
3882
- this.mock(_Helper).expects("updateAll").exactly(bHasGroupLevelCache ? 0 : 1)
4135
+ this.mock(_Helper).expects("updateAll")
4136
+ .exactly(bHasGroupLevelCache || bInFirstLevel ? 0 : 1)
3883
4137
  .withExactArgs(sinon.match.same(oCache.mChangeListeners), "('42')",
3884
4138
  sinon.match.same(oParentNode), {"@$ui5.node.isExpanded" : true});
3885
4139
  const oEntityData = {
@@ -3888,20 +4142,23 @@ sap.ui.define([
3888
4142
  foo : "~foo~"
3889
4143
  };
3890
4144
  const oPostBody = {};
3891
- this.mock(oGroupLevelCache).expects("create")
4145
+ const oCollectionCache = bInFirstLevel ? oCache.oFirstLevel : oGroupLevelCache;
4146
+ this.mock(oCollectionCache).expects("create")
3892
4147
  .withExactArgs("~oGroupLock~", "~oPostPathPromise~", "~sPath~", "~sTransientPredicate~",
3893
4148
  {bar : "~bar~", foo : "~foo~"},
3894
4149
  false, "~fnErrorCallback~", "~fnSubmitCallback~", sinon.match.func)
3895
4150
  .callsFake(function () {
3896
4151
  fnCancelCallback = arguments[8];
3897
- if (!bHasGroupLevelCache) {
3898
- assert.strictEqual(_Helper.getPrivateAnnotation(oParentNode, "cache"),
3899
- oGroupLevelCache);
3900
- }
4152
+ assert.strictEqual(_Helper.getPrivateAnnotation(oParentNode, "cache"),
4153
+ bInFirstLevel ? undefined : oGroupLevelCache);
3901
4154
  _Helper.setPrivateAnnotation(oEntityData, "postBody", oPostBody);
3902
4155
  return new SyncPromise(function (resolve) {
3903
4156
  setTimeout(function () {
3904
4157
  _Helper.setPrivateAnnotation(oEntityData, "predicate", "('ABC')");
4158
+ if (bInFirstLevel) {
4159
+ // Note: #calculateKeyPredicateRH doesn't know better :-(
4160
+ oEntityData["@$ui5.node.level"] = 1;
4161
+ }
3905
4162
  resolve();
3906
4163
  });
3907
4164
  });
@@ -3909,17 +4166,19 @@ sap.ui.define([
3909
4166
  this.mock(_Helper).expects("makeRelativeUrl").withExactArgs("/Foo('42')", "/Foo")
3910
4167
  .returns("~relativeUrl~");
3911
4168
  oCacheMock.expects("addElements")
3912
- .withExactArgs(sinon.match.same(oEntityData), 3, sinon.match.same(oGroupLevelCache), 0)
4169
+ .withExactArgs(sinon.match.same(oEntityData), 3, sinon.match.same(oCollectionCache))
3913
4170
  .callsFake(function () {
3914
4171
  assert.deepEqual(oCache.aElements, ["0", "1", oParentNode, null, "3", "4"]);
3915
4172
  });
3916
- oCacheMock.expects("shiftIndex").withExactArgs(3, +1);
4173
+ const oAdjustDescendantCountExpectation = oCacheMock.expects("adjustDescendantCount")
4174
+ .exactly(bInFirstLevel ? 1 : 0).withExactArgs(sinon.match.same(oEntityData), 3, +1);
3917
4175
 
3918
4176
  // code under test
3919
4177
  const oResult = oCache.create("~oGroupLock~", "~oPostPathPromise~", "~sPath~",
3920
4178
  "~sTransientPredicate~", oEntityData, /*bAtEndOfCreated*/false, "~fnErrorCallback~",
3921
4179
  "~fnSubmitCallback~");
3922
4180
 
4181
+ assert.strictEqual(oAdjustDescendantCountExpectation.callCount, bInFirstLevel ? 1 : 0);
3923
4182
  assert.deepEqual(oPostBody, {"myParent@odata.bind" : "~relativeUrl~"});
3924
4183
  assert.deepEqual(oEntityData, {
3925
4184
  "@$ui5._" : {postBody : oPostBody},
@@ -3932,6 +4191,12 @@ sap.ui.define([
3932
4191
 
3933
4192
  return oResult.then(function (oEntityData0) {
3934
4193
  assert.strictEqual(oEntityData0, oEntityData);
4194
+ assert.deepEqual(oEntityData, {
4195
+ "@$ui5._" : {postBody : oPostBody, predicate : "('ABC')"},
4196
+ "@$ui5.node.level" : 24,
4197
+ bar : "~bar~",
4198
+ foo : "~foo~"
4199
+ });
3935
4200
  assert.deepEqual(oCache.aElements.$byPredicate, {
3936
4201
  "('42')" : oParentNode,
3937
4202
  "('ABC')" : oEntityData
@@ -3939,14 +4204,11 @@ sap.ui.define([
3939
4204
  assert.strictEqual(oCache.aElements.$count, 6);
3940
4205
 
3941
4206
  oCache.aElements[3] = oEntityData;
3942
- oCacheMock.expects("shiftIndex").withExactArgs(3, -1)
3943
- .callsFake(function () {
3944
- assert.deepEqual(oCache.aElements,
3945
- ["0", "1", oParentNode, oEntityData, "3", "4"], "not yet spliced");
3946
- });
3947
4207
  this.mock(_Helper).expects("getPrivateAnnotation")
3948
4208
  .withExactArgs(sinon.match.same(oEntityData), "transientPredicate")
3949
4209
  .returns("('42')"); // just testing ;-)
4210
+ oCacheMock.expects("adjustDescendantCount").exactly(bInFirstLevel ? 1 : 0)
4211
+ .withExactArgs(sinon.match.same(oEntityData), 3, -1);
3950
4212
 
3951
4213
  // code under test
3952
4214
  fnCancelCallback();
@@ -3958,21 +4220,85 @@ sap.ui.define([
3958
4220
  assert.deepEqual(oCache.aElements, ["0", "1", oParentNode, "3", "4"]);
3959
4221
  }.bind(this));
3960
4222
  });
4223
+ });
3961
4224
  });
3962
4225
 
3963
4226
  //*********************************************************************************************
3964
- QUnit.test("create: expandTo > 1", function (assert) {
4227
+ QUnit.test("create: root node", function (assert) {
4228
+ var fnCancelCallback;
4229
+
3965
4230
  const oCache = _AggregationCache.create(this.oRequestor, "Foo", "", {}, {
3966
- expandTo : 2,
4231
+ $ParentNavigationProperty : "myParent",
4232
+ expandTo : 42,
3967
4233
  hierarchyQualifier : "X"
3968
4234
  });
3969
- this.mock(oCache).expects("createGroupLevelCache").never();
3970
- this.mock(_Helper).expects("updateAll").never();
3971
- this.mock(oCache).expects("addElements").never();
4235
+ oCache.aElements = ["0", "1", "2"];
4236
+ oCache.aElements.$byPredicate = {};
4237
+ oCache.aElements.$count = 3;
4238
+ const oCacheMock = this.mock(oCache);
4239
+ oCacheMock.expects("createGroupLevelCache").never();
4240
+ const oEntityData = {
4241
+ bar : "~bar~",
4242
+ foo : "~foo~"
4243
+ };
4244
+ const oPostBody = {};
4245
+ this.mock(oCache.oFirstLevel).expects("create")
4246
+ .withExactArgs("~oGroupLock~", "~oPostPathPromise~", "~sPath~", "~sTransientPredicate~",
4247
+ {bar : "~bar~", foo : "~foo~"},
4248
+ false, "~fnErrorCallback~", "~fnSubmitCallback~", sinon.match.func)
4249
+ .callsFake(function () {
4250
+ fnCancelCallback = arguments[8];
4251
+ _Helper.setPrivateAnnotation(oEntityData, "postBody", oPostBody);
4252
+ return new SyncPromise(function (resolve) {
4253
+ setTimeout(function () {
4254
+ _Helper.setPrivateAnnotation(oEntityData, "predicate", "('ABC')");
4255
+ resolve();
4256
+ });
4257
+ });
4258
+ });
4259
+ this.mock(_Helper).expects("makeRelativeUrl").never();
4260
+ oCacheMock.expects("addElements")
4261
+ .withExactArgs(sinon.match.same(oEntityData), 0, sinon.match.same(oCache.oFirstLevel))
4262
+ .callsFake(function () {
4263
+ assert.deepEqual(oCache.aElements, [null, "0", "1", "2"]);
4264
+ });
3972
4265
 
3973
- assert.throws(function () {
3974
- oCache.create();
3975
- }, new Error("Unsupported expandTo: 2"));
4266
+ // code under test
4267
+ const oResult = oCache.create("~oGroupLock~", "~oPostPathPromise~", "~sPath~",
4268
+ "~sTransientPredicate~", oEntityData, /*bAtEndOfCreated*/false, "~fnErrorCallback~",
4269
+ "~fnSubmitCallback~");
4270
+
4271
+ assert.deepEqual(oPostBody, {});
4272
+ assert.deepEqual(oEntityData, {
4273
+ "@$ui5._" : {postBody : oPostBody},
4274
+ "@$ui5.node.level" : 1,
4275
+ bar : "~bar~",
4276
+ foo : "~foo~"
4277
+ });
4278
+ assert.strictEqual(oCache.aElements.$count, 4);
4279
+ assert.strictEqual(oResult.isPending(), true);
4280
+
4281
+ return oResult.then((oEntityData0) => {
4282
+ assert.strictEqual(oEntityData0, oEntityData);
4283
+ assert.deepEqual(oCache.aElements.$byPredicate, {
4284
+ "('ABC')" : oEntityData
4285
+ });
4286
+ assert.strictEqual(oCache.aElements.$count, 4);
4287
+
4288
+ oCache.aElements[0] = oEntityData;
4289
+ this.mock(_Helper).expects("getPrivateAnnotation")
4290
+ .withExactArgs(sinon.match.same(oEntityData), "transientPredicate")
4291
+ .returns("('42')"); // just testing ;-)
4292
+
4293
+ // code under test
4294
+ fnCancelCallback();
4295
+
4296
+ assert.strictEqual(oCache.aElements.$count, 3);
4297
+ assert.deepEqual(oCache.aElements.$byPredicate, {
4298
+ "('ABC')" : oEntityData
4299
+ });
4300
+ assert.deepEqual(oCache.aElements, ["0", "1", "2"]);
4301
+ });
3976
4302
  });
3977
4303
 
3978
4304
  //*********************************************************************************************
@@ -3985,7 +4311,7 @@ sap.ui.define([
3985
4311
  this.mock(oCache).expects("addElements").never();
3986
4312
 
3987
4313
  assert.throws(function () {
3988
- oCache.create(null, null, "", "", null, /*bAtEndOfCreated*/true);
4314
+ oCache.create(null, null, "", "", {}, /*bAtEndOfCreated*/true);
3989
4315
  }, new Error("Unsupported bAtEndOfCreated"));
3990
4316
 
3991
4317
  oCache.aElements.$byPredicate["('42')"] = {"@$ui5.node.isExpanded" : false};
@@ -3997,7 +4323,7 @@ sap.ui.define([
3997
4323
 
3998
4324
  //*********************************************************************************************
3999
4325
  [false, true].forEach(function (bBreak) {
4000
- QUnit.test(`shiftIndex: break = ${bBreak}`, function (assert) {
4326
+ QUnit.test(`shiftIndex: group level cache, break = ${bBreak}`, function (assert) {
4001
4327
  const oCache = _AggregationCache.create(this.oRequestor, "Foo", "", {}, {
4002
4328
  hierarchyQualifier : "X"
4003
4329
  });
@@ -4007,8 +4333,8 @@ sap.ui.define([
4007
4333
  ID : "node"
4008
4334
  };
4009
4335
  const oElementSkip = {
4010
- "@$ui5._" : {index : -3, parent : "not oGroupLevelCache", placeholder : true},
4011
- "@$ui5.node.level" : 0, // must be ignored
4336
+ "@$ui5._" : {index : -3, parent : "not oGroupLevelCache"},
4337
+ "@$ui5.node.level" : 25,
4012
4338
  ID : "skip"
4013
4339
  };
4014
4340
  const oElementNoBreak = {
@@ -4018,12 +4344,12 @@ sap.ui.define([
4018
4344
  const oElementChange = {
4019
4345
  "@$ui5._" : {index : 4, parent : "~oGroupLevelCache~"},
4020
4346
  "@$ui5.node.level" : 24,
4021
- ID : "change (node)"
4347
+ ID : "change"
4022
4348
  };
4023
- const oPlaceholderChange = {
4024
- "@$ui5._" : {index : 5, parent : "~oGroupLevelCache~", placeholder : true},
4025
- "@$ui5.node.level" : 0, // must be ignored
4026
- ID : "change (placeholder)"
4349
+ const oElementCreated = {
4350
+ "@$ui5._" : {parent : "~oGroupLevelCache~"},
4351
+ "@$ui5.node.level" : 24,
4352
+ ID : "created"
4027
4353
  };
4028
4354
  const oElementBreak = {
4029
4355
  "@$ui5.node.level" : bBreak
@@ -4037,7 +4363,7 @@ sap.ui.define([
4037
4363
  ID : "trap"
4038
4364
  };
4039
4365
  oCache.aElements = ["0", "1", oNode, oElementSkip, oElementNoBreak, oElementChange,
4040
- oPlaceholderChange, oElementBreak, oElementTrap];
4366
+ oElementCreated, oElementBreak, oElementTrap];
4041
4367
 
4042
4368
  // code under test
4043
4369
  oCache.shiftIndex(2, 47);
@@ -4047,8 +4373,8 @@ sap.ui.define([
4047
4373
  "@$ui5.node.level" : 24,
4048
4374
  ID : "node"
4049
4375
  }, {
4050
- "@$ui5._" : {index : -3, parent : "not oGroupLevelCache", placeholder : true},
4051
- "@$ui5.node.level" : 0,
4376
+ "@$ui5._" : {index : -3, parent : "not oGroupLevelCache"},
4377
+ "@$ui5.node.level" : 25,
4052
4378
  ID : "skip"
4053
4379
  }, {
4054
4380
  "@$ui5.node.level" : 24,
@@ -4056,11 +4382,11 @@ sap.ui.define([
4056
4382
  }, {
4057
4383
  "@$ui5._" : {index : 4 + 47, parent : "~oGroupLevelCache~"},
4058
4384
  "@$ui5.node.level" : 24,
4059
- ID : "change (node)"
4385
+ ID : "change"
4060
4386
  }, {
4061
- "@$ui5._" : {index : 5 + 47, parent : "~oGroupLevelCache~", placeholder : true},
4062
- "@$ui5.node.level" : 0,
4063
- ID : "change (placeholder)"
4387
+ "@$ui5._" : {parent : "~oGroupLevelCache~"},
4388
+ "@$ui5.node.level" : 24,
4389
+ ID : "created"
4064
4390
  }, {
4065
4391
  "@$ui5.node.level" : bBreak ? 23 : 24,
4066
4392
  ID : "break"
@@ -4076,117 +4402,201 @@ sap.ui.define([
4076
4402
  });
4077
4403
  });
4078
4404
 
4405
+ //*********************************************************************************************
4406
+ QUnit.test("shiftIndex: oFirstLevel", function (assert) {
4407
+ const oCache = _AggregationCache.create(this.oRequestor, "Foo", "", {}, {
4408
+ hierarchyQualifier : "X"
4409
+ });
4410
+ oCache.aElements = [{
4411
+ "@$ui5._" : {index : 0, parent : oCache.oFirstLevel}
4412
+ }, {
4413
+ "@$ui5._" : {index : 1, parent : oCache.oFirstLevel}
4414
+ }, {
4415
+ "@$ui5._" : {index : 2, parent : oCache.oFirstLevel}
4416
+ }, {
4417
+ "@$ui5._" : {index : 3, parent : oCache.oFirstLevel}
4418
+ }, {
4419
+ "@$ui5._" : {/*index : undefined,*/parent : oCache.oFirstLevel}
4420
+ }, {
4421
+ "@$ui5._" : {index : 0, parent : "~oGroupLevelCache~"}
4422
+ }, {
4423
+ "@$ui5._" : {index : 1, parent : "~oGroupLevelCache~"}
4424
+ }, {
4425
+ "@$ui5._" : {index : 4, parent : oCache.oFirstLevel}
4426
+ }, {
4427
+ "@$ui5._" : {index : 5, parent : oCache.oFirstLevel}
4428
+ }];
4429
+
4430
+ // code under test
4431
+ oCache.shiftIndex(2, 23);
4432
+
4433
+ assert.deepEqual(oCache.aElements.map((oElement) => oElement["@$ui5._"].index),
4434
+ [0, 1, 2, 3 + 23, undefined, 0, 1, 4 + 23, 5 + 23]);
4435
+ });
4436
+
4079
4437
  //*********************************************************************************************
4080
4438
  [
4081
- {parentLeaf : false, parentExpand : true},
4082
- {parentLeaf : false, parentExpand : false, parentMoved : true},
4083
- {parentLeaf : true, parentExpand : false},
4084
- {noParent : true}
4439
+ {firstLevel : true},
4440
+ {firstLevel : false, parentLeaf : false},
4441
+ {firstLevel : false, parentLeaf : true}
4085
4442
  ].forEach(function (oFixture) {
4086
- QUnit.test(`_delete: leaf, ${JSON.stringify(oFixture)}`, function (assert) {
4087
- // Before the delete, the child is at 2 and the parent is at 1 (or missing) - hence the
4088
- // child's level index is 0 (or 2). When restoring, the level index is 3, and the parent
4089
- // possibly moved to index 6. So the child must be restored to 3 (no parent), 5 (parent
4090
- // still at 1) or 10 (parent moved to 6).
4443
+ [false, true].forEach((bCreated) => {
4444
+ const sTitle = `_delete: ${JSON.stringify(oFixture)}, ${bCreated}`;
4445
+
4446
+ QUnit.test(sTitle, function (assert) {
4447
+ var oCountExpectation, oRemoveExpectation;
4448
+
4091
4449
  const oCache = _AggregationCache.create(this.oRequestor, "Foo", "", {}, {
4092
4450
  hierarchyQualifier : "X"
4093
4451
  });
4094
4452
  const fnCallback = sinon.spy();
4095
- const oLevelCache = {
4096
- _delete : mustBeMocked,
4097
- getValue : mustBeMocked
4098
- };
4099
- const oParent = {
4100
- "@$ui5.node.isExpanded" : true
4453
+ const oParentCache = {
4454
+ getValue : mustBeMocked,
4455
+ removeElement : mustBeMocked
4101
4456
  };
4102
4457
 
4103
- if (!oFixture.noParent) {
4104
- oCache.aElements[1] = oParent;
4458
+ const oElement = oCache.aElements[2] = {};
4459
+ if (bCreated) { // simulate a created persisted element
4460
+ oElement["@$ui5.context.isTransient"] = false;
4461
+ }
4462
+ oCache.aElements[3] = "~oParent~";
4463
+ if (oFixture.firstLevel) {
4464
+ oCache.oFirstLevel = oParentCache;
4105
4465
  }
4106
- oCache.aElements[2] = "~oElement~";
4107
4466
  const oHelperMock = this.mock(_Helper);
4108
- oHelperMock.expects("getPrivateAnnotation").withExactArgs("~oElement~", "parent")
4109
- .returns(oLevelCache);
4110
- oHelperMock.expects("getPrivateAnnotation").withExactArgs("~oElement~", "index")
4111
- .returns(oFixture.noParent ? 2 : 0);
4112
- const oLevelCacheMock = this.mock(oLevelCache);
4113
- const oDeleteExpectation = oLevelCacheMock.expects("_delete")
4114
- .withExactArgs("~groupLock~", "~editUrl~", oFixture.noParent ? "2" : "0",
4115
- "~etagEntity~", sinon.match.func)
4116
- .returns("~promise~");
4467
+ oHelperMock.expects("getPrivateAnnotation")
4468
+ .withExactArgs(sinon.match.same(oElement), "parent")
4469
+ .returns(oParentCache);
4470
+ oHelperMock.expects("getPrivateAnnotation")
4471
+ .withExactArgs(sinon.match.same(oElement), "predicate")
4472
+ .returns("~predicate~");
4473
+ this.mock(this.oRequestor).expects("request")
4474
+ .withExactArgs("DELETE", "~editUrl~", "~groupLock~", {
4475
+ "If-Match" : sinon.match.same(oElement)
4476
+ })
4477
+ .callsFake(() => {
4478
+ this.mock(_Cache).expects("getElementIndex")
4479
+ .withExactArgs(sinon.match.same(oCache.aElements), "~predicate~", 2)
4480
+ .returns(4);
4481
+ oHelperMock.expects("getPrivateAnnotation")
4482
+ .withExactArgs(sinon.match.same(oElement), "index", 0).returns("~index~");
4483
+ const oParentCacheMock = this.mock(oParentCache);
4484
+ oRemoveExpectation = oParentCacheMock.expects("removeElement")
4485
+ .withExactArgs("~index~", "~predicate~").returns("~iIndexInParentCache~");
4486
+ oHelperMock.expects("getPrivateAnnotation")
4487
+ .withExactArgs(sinon.match.same(oElement), "descendants", 0)
4488
+ .returns(oFixture.firstLevel ? 3 : 0);
4489
+ oParentCacheMock.expects("removeElement").exactly(oFixture.firstLevel ? 3 : 0)
4490
+ .withExactArgs("~iIndexInParentCache~");
4491
+ this.mock(oCache).expects("adjustDescendantCount")
4492
+ .exactly(oFixture.firstLevel ? 1 : 0)
4493
+ .withExactArgs(sinon.match.same(oElement), 4, oFixture.firstLevel ? -4 : -1);
4494
+ oCountExpectation = this.mock(oParentCache).expects("getValue")
4495
+ .exactly(oFixture.firstLevel ? 0 : 1)
4496
+ .withExactArgs("$count").returns(oFixture.parentLeaf ? 0 : 5);
4497
+ this.mock(oCache).expects("makeLeaf").exactly(oFixture.parentLeaf ? 1 : 0)
4498
+ .withExactArgs("~oParent~");
4499
+ this.mock(oCache).expects("shiftIndex").exactly(bCreated ? 0 : 1)
4500
+ .withExactArgs(4, oFixture.firstLevel ? -4 : -1);
4501
+ this.mock(oCache).expects("removeElement")
4502
+ .withExactArgs(4, "~predicate~");
4503
+
4504
+ return Promise.resolve();
4505
+ });
4117
4506
 
4118
- assert.strictEqual(
4119
- // code under test
4120
- oCache._delete("~groupLock~", "~editUrl~", "2", "~etagEntity~", fnCallback),
4121
- "~promise~");
4507
+ // code under test
4508
+ const oDeletePromise = oCache._delete("~groupLock~", "~editUrl~", "2", "n/a", fnCallback);
4122
4509
 
4123
- const oCacheMock = this.mock(oCache);
4124
- const oShiftExpectation1 = oCacheMock.expects("shiftIndex").withExactArgs(2, -1);
4125
- oHelperMock.expects("getPrivateAnnotation").withExactArgs("~oElement~", "predicate")
4126
- .returns("~predicate~");
4127
- const oRemoveExpectation = oCacheMock.expects("removeElement")
4128
- .withExactArgs(sinon.match.same(oCache.aElements), 2, "~predicate~", "");
4129
- oLevelCacheMock.expects("getValue").exactly(oFixture.noParent ? 0 : 1)
4130
- .withExactArgs("$count").returns(oFixture.parentLeaf ? 0 : 5);
4131
- oHelperMock.expects("getPrivateAnnotation").exactly(oFixture.parentLeaf ? 1 : 0)
4132
- .withExactArgs(sinon.match.same(oParent), "predicate").returns("~predicate~");
4133
- oHelperMock.expects("updateAll").exactly(oFixture.parentLeaf ? 1 : 0)
4134
- .withExactArgs(sinon.match.same(oCache.mChangeListeners), "~predicate~",
4135
- sinon.match.same(oParent), {"@$ui5.node.isExpanded" : undefined});
4510
+ assert.ok(oDeletePromise.isPending(), "a SyncPromise");
4136
4511
 
4137
- // code under test - callback deleting
4138
- oDeleteExpectation.firstCall.args[4](0, -1);
4512
+ return oDeletePromise.then(function () {
4513
+ assert.strictEqual(fnCallback.callCount, 1);
4514
+ assert.deepEqual(fnCallback.args[0], [4, -1]);
4515
+ assert.ok(oRemoveExpectation.calledBefore(oCountExpectation));
4516
+ });
4517
+ });
4518
+ });
4519
+ });
4139
4520
 
4140
- if (oFixture.parentMoved) {
4141
- delete oCache.aElements[1];
4142
- oCache.aElements[6] = oParent;
4143
- }
4144
- assert.ok(oShiftExpectation1.calledBefore(oRemoveExpectation));
4145
- assert.strictEqual(fnCallback.callCount, 1);
4146
- assert.deepEqual(fnCallback.args[0], [2, -1]);
4147
- if (oFixture.parentLeaf) {
4148
- assert.notOk("@$ui5.node.isExpanded" in oParent);
4149
- }
4521
+ //*********************************************************************************************
4522
+ QUnit.test("_delete: request fails", function (assert) {
4523
+ const oCache = _AggregationCache.create(this.oRequestor, "Foo", "", {}, {
4524
+ hierarchyQualifier : "X"
4525
+ });
4526
+ const fnCallback = sinon.spy();
4527
+ const oElement = {};
4150
4528
 
4151
- // parent index is 6 or 1, child index in level cache is 3 (from the callback)
4152
- let iExpectedIndex = oFixture.parentMoved ? 10 : 5;
4153
- if (oFixture.noParent) {
4154
- iExpectedIndex = 3;
4155
- }
4156
- const oRestoreExpectation = this.mock(oCache).expects("restoreElement")
4157
- .withExactArgs(sinon.match.same(oCache.aElements), iExpectedIndex, "~oElement~", "");
4158
- const oShiftExpectation2 = oCacheMock.expects("shiftIndex")
4159
- .withExactArgs(iExpectedIndex, 1);
4160
- oLevelCacheMock.expects("getValue").exactly(oFixture.noParent ? 0 : 1)
4161
- .withExactArgs("$count").returns(oFixture.parentExpand ? 1 : 5);
4162
- oHelperMock.expects("getPrivateAnnotation").exactly(oFixture.parentExpand ? 1 : 0)
4163
- .withExactArgs(sinon.match.same(oParent), "predicate").returns("~predicate~");
4164
- oHelperMock.expects("updateAll").exactly(oFixture.parentExpand ? 1 : 0)
4165
- .withExactArgs(sinon.match.same(oCache.mChangeListeners), "~predicate~",
4166
- sinon.match.same(oParent), {"@$ui5.node.isExpanded" : true});
4167
- oHelperMock.expects("setPrivateAnnotation").withExactArgs("~oElement~", "index", 3);
4529
+ oCache.aElements[2] = oElement;
4530
+ this.mock(this.oRequestor).expects("request")
4531
+ .withExactArgs("DELETE", "~editUrl~", "~groupLock~",
4532
+ {"If-Match" : sinon.match.same(oElement)})
4533
+ .returns(Promise.reject("~error~"));
4534
+
4535
+ // code under test
4536
+ const oDeletePromise = oCache._delete("~groupLock~", "~editUrl~", "2", "n/a", fnCallback);
4168
4537
 
4169
- // code under test - callback reinserting
4170
- oDeleteExpectation.firstCall.args[4](3, 1);
4538
+ assert.ok(oDeletePromise.isPending(), "a SyncPromise");
4171
4539
 
4172
- assert.ok(oRestoreExpectation.calledBefore(oShiftExpectation2));
4173
- assert.strictEqual(fnCallback.callCount, 2);
4174
- assert.deepEqual(fnCallback.args[1], [iExpectedIndex, 1]);
4540
+ return oDeletePromise.then(function () {
4541
+ assert.ok(false);
4542
+ }, function (oError) {
4543
+ assert.strictEqual(oError, "~error~");
4544
+ assert.strictEqual(fnCallback.callCount, 0);
4545
+ });
4175
4546
  });
4176
- });
4177
4547
 
4178
4548
  //*********************************************************************************************
4179
- QUnit.test("_delete: expandTo > 1", function (assert) {
4549
+ QUnit.test("_delete: transient node", function (assert) {
4550
+ const oCache = _AggregationCache.create(this.oRequestor, "Foo", "", {}, {
4551
+ hierarchyQualifier : "X"
4552
+ });
4553
+ const oElement = {
4554
+ "@$ui5.context.isTransient" : true
4555
+ };
4556
+ const oParentCache = {
4557
+ _delete : mustBeMocked
4558
+ };
4559
+
4560
+ oCache.aElements[2] = oElement;
4561
+ const oHelperMock = this.mock(_Helper);
4562
+ oHelperMock.expects("getPrivateAnnotation")
4563
+ .withExactArgs(sinon.match.same(oElement), "predicate").returns("n/a");
4564
+ oHelperMock.expects("getPrivateAnnotation")
4565
+ .withExactArgs(sinon.match.same(oElement), "parent")
4566
+ .returns(oParentCache);
4567
+ oHelperMock.expects("getPrivateAnnotation")
4568
+ .withExactArgs(sinon.match.same(oElement), "transientPredicate")
4569
+ .returns("~transientPredicate~");
4570
+ this.mock(oParentCache).expects("_delete")
4571
+ .withExactArgs("~groupLock~", "~editUrl~", "~transientPredicate~")
4572
+ .returns("~promise~");
4573
+
4574
+ assert.strictEqual(
4575
+ // code under test
4576
+ oCache._delete("~groupLock~", "~editUrl~", "2"),
4577
+ "~promise~"
4578
+ );
4579
+ });
4580
+
4581
+ //*********************************************************************************************
4582
+ QUnit.test("_delete: expanded node", function (assert) {
4180
4583
  const oCache = _AggregationCache.create(this.oRequestor, "Foo", "", {}, {
4181
- expandTo : 2,
4182
4584
  hierarchyQualifier : "X"
4183
4585
  });
4586
+ const oElement = {
4587
+ "@$ui5.node.isExpanded" : true
4588
+ };
4589
+ oCache.aElements[2] = oElement;
4590
+
4591
+ this.mock(_Helper).expects("getPrivateAnnotation")
4592
+ .withExactArgs(sinon.match.same(oElement), "predicate").returns("(42)");
4593
+ this.mock(this.oRequestor).expects("request").never();
4184
4594
  this.mock(oCache).expects("removeElement").never();
4185
4595
  this.mock(_Helper).expects("updateAll").never();
4186
4596
 
4187
4597
  assert.throws(function () {
4188
- oCache._delete();
4189
- }, new Error("Unsupported expandTo: 2"));
4598
+ oCache._delete("~oGroupLock~", "edit/url", "2");
4599
+ }, new Error("Unsupported expanded node: Foo(42)"));
4190
4600
  });
4191
4601
 
4192
4602
  //*********************************************************************************************
@@ -4219,4 +4629,81 @@ sap.ui.define([
4219
4629
  // code under test
4220
4630
  oCache.resetChangesForPath("~sPath~");
4221
4631
  });
4632
+
4633
+ //*********************************************************************************************
4634
+ // in: array of arrays with level, descendants
4635
+ // isAncestorOf gives the expected calls of the function and its results
4636
+ // leaf: index of a node becoming a leaf
4637
+ // out: array of descendants values
4638
+ [{
4639
+ // Placeholder at 3 must be ignored, 2 and 1 are ancestors, 0 must never be looked at
4640
+ // Note: level -1 is unrealistic, but enforces that the loop stops at level 1
4641
+ in : [[-1, 0], [1, 30], [2, 29], [0, undefined], [3, 0], [3, 1]],
4642
+ isAncestorOf : [[2, 5, true]],
4643
+ out : [0, 7, 6, undefined, 0, 1]
4644
+ }, { // Placeholder at 2 must be ignored, but 1 is no ancestor
4645
+ in : [[1, 30], [2, 0], [0, undefined], [3, 1]],
4646
+ isAncestorOf : [[1, 3, false], [0, 3, true]],
4647
+ out : [7, 0, undefined, 1]
4648
+ }, { // nothing to do, no visible ancestor
4649
+ in : [[1, 8]],
4650
+ out : [8]
4651
+ }, { // root becomes leaf
4652
+ in : [[1, 23], [2, 0]],
4653
+ leaf : 0,
4654
+ out : [0, 0]
4655
+ }, { // 1 becomes leaf
4656
+ in : [[1, 24], [2, 23], [3, 0]],
4657
+ leaf : 1,
4658
+ out : [1, 0, 0]
4659
+ }].forEach(function (oFixture, i) {
4660
+ QUnit.test("adjustDescendantCount #" + i, function (assert) {
4661
+ const oCache = _AggregationCache.create(this.oRequestor, "Foo", "", {}, {
4662
+ hierarchyQualifier : "X"
4663
+ });
4664
+ oCache.aElements = oFixture.in.map(([iLevel, iDescendants]) => ({
4665
+ "@$ui5._" : {descendants : iDescendants},
4666
+ "@$ui5.node.level" : iLevel
4667
+ }));
4668
+
4669
+ const oCacheMock = this.mock(oCache);
4670
+ if (oFixture.isAncestorOf) {
4671
+ oFixture.isAncestorOf.forEach(([iIndex0, iIndex1, bResult]) => {
4672
+ oCacheMock.expects("isAncestorOf").withExactArgs(iIndex0, iIndex1).returns(bResult);
4673
+ });
4674
+ } else {
4675
+ oCacheMock.expects("isAncestorOf").never();
4676
+ }
4677
+ oCacheMock.expects("makeLeaf").exactly("leaf" in oFixture ? 1 : 0)
4678
+ .withExactArgs(sinon.match.same(oCache.aElements[oFixture.leaf]));
4679
+
4680
+ const iIndex = oFixture.in.length - 1;
4681
+ // code under test
4682
+ oCache.adjustDescendantCount(oCache.aElements[iIndex], iIndex, -23);
4683
+
4684
+ assert.deepEqual(
4685
+ oCache.aElements.map((oElement) => oElement["@$ui5._"].descendants),
4686
+ oFixture.out);
4687
+ });
4688
+ });
4689
+
4690
+ //*********************************************************************************************
4691
+ QUnit.test("makeLeaf", function (assert) {
4692
+ const oCache = _AggregationCache.create(this.oRequestor, "Foo", "", {}, {
4693
+ hierarchyQualifier : "X"
4694
+ });
4695
+ const oElement = {"@$ui5.node.isExpanded" : true};
4696
+
4697
+ this.mock(_Helper).expects("getPrivateAnnotation")
4698
+ .withExactArgs(sinon.match.same(oElement), "predicate")
4699
+ .returns("~predicate~");
4700
+ this.mock(_Helper).expects("updateAll")
4701
+ .withExactArgs(sinon.match.same(oCache.mChangeListeners), "~predicate~",
4702
+ sinon.match.same(oElement), {"@$ui5.node.isExpanded" : undefined});
4703
+
4704
+ // code under test
4705
+ oCache.makeLeaf(oElement);
4706
+
4707
+ assert.notOk("@$ui5.node.isExpanded" in oElement);
4708
+ });
4222
4709
  });