@openui5/sap.ui.core 1.119.1 → 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
@@ -4,7 +4,6 @@
4
4
  sap.ui.define([
5
5
  "sap/base/Log",
6
6
  "sap/base/util/uid",
7
- "sap/base/util/UriParameters",
8
7
  "sap/m/ColumnListItem",
9
8
  "sap/m/CustomListItem",
10
9
  "sap/m/FlexBox",
@@ -16,6 +15,7 @@ sap.ui.define([
16
15
  "sap/ui/core/Configuration",
17
16
  "sap/ui/core/Messaging",
18
17
  "sap/ui/core/Rendering",
18
+ "sap/ui/core/Supportability",
19
19
  "sap/ui/core/mvc/Controller",
20
20
  "sap/ui/core/mvc/View",
21
21
  "sap/ui/model/ChangeReason",
@@ -31,15 +31,16 @@ sap.ui.define([
31
31
  "sap/ui/model/odata/v4/ODataPropertyBinding",
32
32
  "sap/ui/model/odata/v4/ValueListType",
33
33
  "sap/ui/model/odata/v4/lib/_Helper",
34
+ "sap/ui/security/Security",
34
35
  "sap/ui/test/TestUtils",
35
36
  "sap/ui/util/XMLHelper",
36
37
  // load Table resources upfront to avoid loading times > 1 second for the first test using Table
37
38
  "sap/ui/table/Table"
38
- ], function (Log, uid, UriParameters, ColumnListItem, CustomListItem, FlexBox, _MessageStrip, Text,
39
- Device, EventProvider, SyncPromise, Configuration, Messaging, Rendering, Controller, View,
40
- ChangeReason, Filter, FilterOperator, FilterType, Sorter, OperationMode, AnnotationHelper,
41
- ODataListBinding, ODataMetaModel, ODataModel, ODataPropertyBinding, ValueListType, _Helper,
42
- TestUtils, XMLHelper) {
39
+ ], function (Log, uid, ColumnListItem, CustomListItem, FlexBox, _MessageStrip, Text,
40
+ Device, EventProvider, SyncPromise, Configuration, Messaging, Rendering, Supportability,
41
+ Controller, View, ChangeReason, Filter, FilterOperator, FilterType, Sorter, OperationMode,
42
+ AnnotationHelper, ODataListBinding, ODataMetaModel, ODataModel, ODataPropertyBinding,
43
+ ValueListType, _Helper, Security, TestUtils, XMLHelper) {
43
44
  /*eslint no-sparse-arrays: 0, "max-len": ["error", {"code": 100,
44
45
  "ignorePattern": "/sap/opu/odata4/|\" :$|\" : \\{$|\\{meta>"}], */
45
46
  "use strict";
@@ -56,7 +57,7 @@ sap.ui.define([
56
57
  rSkip = /&\$skip=(\d+)/, // $skip=<number>
57
58
  sTeaBusi = "/sap/opu/odata4/IWBEP/TEA/default/IWBEP/TEA_BUSI/0001/",
58
59
  // the timeout for the tests and for waitForChanges in millseconds, 0 = keep defaults
59
- iTestTimeout = parseInt(UriParameters.fromQuery(window.location.search).get("timeout")),
60
+ iTestTimeout = parseInt(new URLSearchParams(window.location.search).get("timeout")),
60
61
  rTop = /&\$top=(\d+)/, // $top=<number>
61
62
  rTransientPredicate = /\(\$uid=[-\w]+\)/g;
62
63
 
@@ -121,22 +122,32 @@ sap.ui.define([
121
122
  } // else: do not spam the output ;-)
122
123
  }
123
124
 
124
- function visitElements(aElements, bSkipByPredicate = false, iLevelOffset = 0) {
125
- aElements.forEach((oElement) => {
126
- const iIndex = _Helper.getPrivateAnnotation(oElement, "index");
125
+ function visitElements(aElements, bSkipByPredicate = false, iLevelOffset = 0,
126
+ iIndexOffset = 0) {
127
+ aElements.forEach((oElement, i) => {
128
+ let iIndex = _Helper.getPrivateAnnotation(oElement, "index");
127
129
  // Note: "@$ui5.node.level" is outdated after #move!
128
130
  const iLevel = oElement["@$ui5.node.level"] + iLevelOffset;
129
131
  const oParent = aParentByLevel[iLevel];
132
+ if (oParent === aParentByLevel[0] && iIndex !== undefined) {
133
+ iIndex += iIndexOffset;
134
+ }
130
135
  const bPlaceholder = _Helper.hasPrivateAnnotation(oElement, "placeholder");
131
136
 
132
137
  if (oParent) {
133
138
  strictEqual(_Helper.getPrivateAnnotation(oElement, "parent"), oParent,
134
- `${sTitle}: "parent" @ level ${iLevel}, index ${iIndex}`);
135
- strictEqual(oParent.aElements.indexOf(oElement),
136
- bPlaceholder
137
- ? -1
138
- : iIndex,
139
- `${sTitle}: "index" @ level ${iLevel}, index ${iIndex}`);
139
+ `${sTitle}: "parent" @ level ${iLevel}, #${i}`);
140
+ if ("@$ui5.context.isTransient" in oElement) {
141
+ strictEqual(iIndex, undefined,
142
+ `${sTitle}: created persisted @ level ${iLevel}, #${i}`);
143
+ } else if (bPlaceholder) {
144
+ strictEqual(oParent.aElements.indexOf(oElement), -1,
145
+ `${sTitle}: placeholder @ level ${iLevel}, #${i}`);
146
+ } else {
147
+ strictEqual(iIndex,
148
+ oParent.aElements.indexOf(oElement) - oParent.aElements.$created,
149
+ `${sTitle}: $skip index @ level ${iLevel}, #${i}`);
150
+ }
140
151
  } else {
141
152
  assert.ok(false, `${sTitle}: no known parent for level ${iLevel}`);
142
153
  }
@@ -163,7 +174,8 @@ sap.ui.define([
163
174
 
164
175
  const aSpliced = _Helper.getPrivateAnnotation(oElement, "spliced");
165
176
  if (aSpliced) {
166
- visitElements(aSpliced, true, iLevel + 1 - aSpliced[0]["@$ui5.node.level"]);
177
+ visitElements(aSpliced, true, iLevel + 1 - aSpliced[0]["@$ui5.node.level"],
178
+ iIndex - aSpliced.$index);
167
179
  }
168
180
  });
169
181
  }
@@ -177,7 +189,11 @@ sap.ui.define([
177
189
  true, `${sTitle}: $byPredicate[${sPredicate}] in aElements`);
178
190
  }
179
191
 
180
- for (let i = 0, n = oListBinding.getAggregation().expandTo || 1; i <= n; i += 1) {
192
+ let iExpandTo = oListBinding.getAggregation().expandTo || 1;
193
+ if (iExpandTo === Number.MAX_SAFE_INTEGER) {
194
+ iExpandTo = 99; // avoid "Invalid array length" :-)
195
+ }
196
+ for (let i = 0; i <= iExpandTo; i += 1) {
181
197
  // Note: level 0 or 1 is used for initial placeholders of 1st level cache!
182
198
  aParentByLevel[i] = oListBinding.oCache.oFirstLevel;
183
199
  }
@@ -224,6 +240,9 @@ sap.ui.define([
224
240
  return vText !== undefined ? String(vText) : "";
225
241
  });
226
242
  });
243
+ while (aExpectedContent.length < aRows.length) { // pad with "empty" rows
244
+ aExpectedContent.push(aExpectedContent[0].slice().fill(""));
245
+ }
227
246
  assert.deepEqual(aRows.map(function (oRow) {
228
247
  return oRow.getCells().map(function (oCell) {
229
248
  return oCell.getText ? oCell.getText() : oCell.getValue();
@@ -476,7 +495,8 @@ sap.ui.define([
476
495
  oDocument = XMLHelper.parse(
477
496
  '<mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" xmlns:plugins="sap.m.plugins"'
478
497
  + ' xmlns:t="sap.ui.table" xmlns:trm="sap.ui.table.rowmodes"'
479
- + ' xmlns:template="http://schemas.sap.com/sapui5/extension/sap.ui.core.template/1">'
498
+ + ' xmlns:template="http://schemas.sap.com/sapui5/extension/sap.ui.core.template/1"'
499
+ + (sViewXML.startsWith(" template:require") ? "" : ">")
480
500
  + sViewXML
481
501
  + "</mvc:View>",
482
502
  "application/xml"
@@ -2326,7 +2346,7 @@ sap.ui.define([
2326
2346
  dRetryAfter = new Date(),
2327
2347
  sView = '<Text text="{/EMPLOYEES(\'1\')/ID}"/>';
2328
2348
 
2329
- this.mock(Configuration).expects("getStatisticsEnabled").withExactArgs()
2349
+ this.mock(Supportability).expects("isStatisticsEnabled").withExactArgs()
2330
2350
  .returns(true);
2331
2351
  oModel = this.createModel("/sap/statistics/", {groupId : "$direct"}, {
2332
2352
  "/sap/statistics/$metadata?sap-statistics=true"
@@ -2389,7 +2409,7 @@ sap.ui.define([
2389
2409
  QUnit.test("sap-statistics for $batch", function (assert) {
2390
2410
  var oModel;
2391
2411
 
2392
- this.mock(Configuration).expects("getStatisticsEnabled").withExactArgs().returns(true);
2412
+ this.mock(Supportability).expects("isStatisticsEnabled").withExactArgs().returns(true);
2393
2413
  oModel = this.createModel("/sap/statistics/", {earlyRequests : true}, {
2394
2414
  "HEAD /sap/statistics/?sap-statistics=true" : {},
2395
2415
  "/sap/statistics/$metadata?sap-statistics=true"
@@ -4812,7 +4832,6 @@ sap.ui.define([
4812
4832
 
4813
4833
  that.expectRequest({
4814
4834
  batchNo : 2,
4815
- method : "GET",
4816
4835
  url : "SalesOrderList('1')/SO_2_SOITEM('0010')/SOITEM_2_PRODUCT"
4817
4836
  + "?sap-client=123&$select=ProductID"
4818
4837
  + "&$expand=PRODUCT_2_BP($select=BusinessPartnerID,CompanyName)"
@@ -4826,7 +4845,6 @@ sap.ui.define([
4826
4845
  })
4827
4846
  .expectRequest({
4828
4847
  batchNo : 2,
4829
- method : "GET",
4830
4848
  url : "SalesOrderList('1')/SO_2_SOITEM('0010')?sap-client=123"
4831
4849
  + "&$select=SOITEM_2_SCHDL"
4832
4850
  + "&$expand=SOITEM_2_SCHDL($select=ItemKey,ScheduleKey)"
@@ -6357,8 +6375,9 @@ sap.ui.define([
6357
6375
  // JIRA: CPOUI5ODATAV4-121
6358
6376
  testXMLTemplating("Operation parameters with sap.ui.model.odata.v4.AnnotationHelper.format",
6359
6377
  "createTeaBusiModel",
6360
- '<template:alias name="format" value="sap.ui.model.odata.v4.AnnotationHelper.format">\
6361
- <template:alias name="value" value="sap.ui.model.odata.v4.AnnotationHelper.value">\
6378
+ ' template:require="{\'AnnotationHelper\':\'sap/ui/model/odata/v4/AnnotationHelper\'}">\
6379
+ <template:alias name="format" value="AnnotationHelper.format">\
6380
+ <template:alias name="value" value="AnnotationHelper.value">\
6362
6381
  <FlexBox id="form" binding="{/ChangeTeamBudgetByID(...)}">\
6363
6382
  <FlexBox binding="{$Parameter}">\
6364
6383
  <template:repeat list="{meta>/ChangeTeamBudgetByID/$Action/0/$Parameter}" var="param">\
@@ -6408,7 +6427,8 @@ sap.ui.define([
6408
6427
  testXMLTemplating(
6409
6428
  "Annotations on operations and parameters sap.ui.model.odata.v4.AnnotationHelper.format",
6410
6429
  "createSpecialCasesModel",
6411
- '<template:alias name="format" value="sap.ui.model.odata.v4.AnnotationHelper.format">\
6430
+ ' template:require="{\'AnnotationHelper\':\'sap/ui/model/odata/v4/AnnotationHelper\'}">\
6431
+ <template:alias name="format" value="AnnotationHelper.format">\
6412
6432
  <FlexBox binding="{special.cases.SendAutograph(...)}"\
6413
6433
  visible="{meta>/Artists/special.cases.SendAutograph\
6414
6434
  @Org.OData.Core.V1.OperationAvailable@@format}">\
@@ -7022,7 +7042,6 @@ sap.ui.define([
7022
7042
  })
7023
7043
  .expectRequest({
7024
7044
  batchNo : 2,
7025
- method : "GET",
7026
7045
  url : "SalesOrderList?$select=SalesOrderID"
7027
7046
  + "&$filter=not (SalesOrderID eq '0500000002'"
7028
7047
  + " or SalesOrderID eq '0500000003')"
@@ -7074,7 +7093,6 @@ sap.ui.define([
7074
7093
  })
7075
7094
  .expectRequest({
7076
7095
  batchNo : 2,
7077
- method : "GET",
7078
7096
  url : "SalesOrderList?$select=SalesOrderID"
7079
7097
  + "&$filter=not (SalesOrderID eq '0500000002')&$skip=2&$top=4"
7080
7098
  }, {
@@ -7716,7 +7734,7 @@ sap.ui.define([
7716
7734
  assert.strictEqual(fnSpy.callCount, 1, "1st #fetchUI5Type");
7717
7735
  assert.strictEqual(oType.getConstraints().maxLength, 40,
7718
7736
  "Don't try this at home, kids!");
7719
- sap.ui.test.TestUtils.withNormalizedMessages(function () {
7737
+ TestUtils.withNormalizedMessages(function () {
7720
7738
  assert.throws(function () {
7721
7739
  oType.validateValue("0123456789012345678901234567890123456789+");
7722
7740
  }, /EnterTextMaxLength 40/);
@@ -7734,7 +7752,7 @@ sap.ui.define([
7734
7752
  assert.strictEqual(fnSpy.callCount, 2, "2nd #fetchUI5Type");
7735
7753
  assert.strictEqual(oType.getConstraints().maxLength, 16,
7736
7754
  "Don't try this at home, kids!");
7737
- sap.ui.test.TestUtils.withNormalizedMessages(function () {
7755
+ TestUtils.withNormalizedMessages(function () {
7738
7756
  assert.throws(function () {
7739
7757
  oType.validateValue("0123456789ABCDEF+");
7740
7758
  }, /EnterTextMaxLength 16/);
@@ -19802,7 +19820,6 @@ sap.ui.define([
19802
19820
  }, createErrorInsideBatch())
19803
19821
  .expectRequest({
19804
19822
  batchNo : 7, // from the binding's reset due to the failed DELETE
19805
- method : "GET",
19806
19823
  url : "SalesOrderList?$count=true"
19807
19824
  + "&$filter=(LifecycleStatus eq 'N') and not (SalesOrderID eq '2')"
19808
19825
  + "&$select=GrossAmount,SalesOrderID&$orderby=GrossAmount&$skip=0&$top=4"
@@ -21045,6 +21062,11 @@ sap.ui.define([
21045
21062
  groupLevels : ["LifecycleStatus"]
21046
21063
  }
21047
21064
  });
21065
+
21066
+ assert.throws(function () {
21067
+ // code under test (JIRA: CPOUI5ODATAV4-2337)
21068
+ oListBinding.getHeaderContext().isAncestorOf(/*don't care*/);
21069
+ }, new Error("Missing recursive hierarchy"));
21048
21070
  });
21049
21071
  });
21050
21072
 
@@ -24789,7 +24811,7 @@ sap.ui.define([
24789
24811
  // JIRA: CPOUI5ODATAV4-1643
24790
24812
  //
24791
24813
  // Request various side effects that do not affect the hierarchy (JIRA: CPOUI5ODATAV4-1785).
24792
- // Check that create, delete, and refresh are not supported (JIRA: CPOUI5ODATAV4-1851).
24814
+ // Check that refresh is not supported (JIRA: CPOUI5ODATAV4-1851).
24793
24815
  // Additionally, ODLB#getDownloadUrl is tested (JIRA: CPOUI5ODATAV4-1920, BCP: 2370011296).
24794
24816
  // Retrieve "DistanceFromRoot" property path via ODLB#getAggregation (JIRA: CPOUI5ODATAV4-1961).
24795
24817
  //
@@ -24804,7 +24826,7 @@ sap.ui.define([
24804
24826
  // expanded to reveal the kept-alive node.
24805
24827
  // JIRA: CPOUI5ODATAV4-2030
24806
24828
  //
24807
- // The whole tree is expanded to two levels (JIRA: CPOUI5ODATAV4-2095).
24829
+ // The whole tree is expanded to -two-all levels (JIRA: CPOUI5ODATAV4-2095/-2151).
24808
24830
  // Selection keeps a context implicitly alive (JIRA: CPOUI5ODATAV4-2053).
24809
24831
  // Ensure that unchanged $$aggregation is ignored (BCP: 2370045709).
24810
24832
  //
@@ -24818,7 +24840,7 @@ sap.ui.define([
24818
24840
  var sExpectedDownloadUrl
24819
24841
  = "/special/cases/Artists?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
24820
24842
  + "HierarchyNodes=$root/Artists,HierarchyQualifier='OrgChart'"
24821
- + ",NodeProperty='_/NodeID',Levels=999)"
24843
+ + ",NodeProperty='_/NodeID')"
24822
24844
  + "&$select=ArtistID,IsActiveEntity,_/DistanceFromRoot,_/DrillState,_/NodeID"
24823
24845
  + "&$expand=BestFriend($select=ArtistID,IsActiveEntity,Name)",
24824
24846
  oHeaderContext,
@@ -24896,6 +24918,17 @@ sap.ui.define([
24896
24918
  assert.strictEqual(oListBinding.getDownloadUrl(), sExpectedDownloadUrl,
24897
24919
  "JIRA: CPOUI5ODATAV4-1920, CPOUI5ODATAV4-2275");
24898
24920
 
24921
+ assert.throws(function () {
24922
+ // code under test (JIRA: CPOUI5ODATAV4-2337)
24923
+ oHeaderContext.isAncestorOf(oRoot);
24924
+ }, new Error("Not currently part of a recursive hierarchy: /Artists"));
24925
+ assert.throws(function () {
24926
+ // code under test (JIRA: CPOUI5ODATAV4-2337)
24927
+ oRoot.isAncestorOf(oHeaderContext);
24928
+ }, new Error("Not currently part of a recursive hierarchy: /Artists"));
24929
+ // code under test
24930
+ assert.strictEqual(oRoot.isAncestorOf(oRoot), true, "JIRA: CPOUI5ODATAV4-2337");
24931
+
24899
24932
  checkTable("root is leaf", assert, oTable, [
24900
24933
  "/Artists(ArtistID='0',IsActiveEntity=true)"
24901
24934
  ], [
@@ -25295,7 +25328,7 @@ sap.ui.define([
25295
25328
  batchNo : 9,
25296
25329
  url : "Artists?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
25297
25330
  + "HierarchyNodes=$root/Artists,HierarchyQualifier='OrgChart'"
25298
- + ",NodeProperty='_/NodeID',Levels=2)&$select=ArtistID,IsActiveEntity"
25331
+ + ",NodeProperty='_/NodeID')&$select=ArtistID,IsActiveEntity"
25299
25332
  + ",_/DescendantCount,_/DistanceFromRoot,_/DrillState,_/NodeID"
25300
25333
  + "&$expand=BestFriend($select=ArtistID,IsActiveEntity,Name)"
25301
25334
  + "&$count=true&$skip=0&$top=3"
@@ -25333,7 +25366,7 @@ sap.ui.define([
25333
25366
  // code under test
25334
25367
  // Note: overall count must not change here, just the "expansion state"
25335
25368
  oListBinding.setAggregation({
25336
- expandTo : 2,
25369
+ expandTo : Number.MAX_SAFE_INTEGER,
25337
25370
  hierarchyQualifier : "OrgChart"
25338
25371
  });
25339
25372
 
@@ -25368,16 +25401,17 @@ sap.ui.define([
25368
25401
  // no additional request for same aggregation data
25369
25402
  // code under test (BCP: 2370045709)
25370
25403
  oListBinding.setAggregation({
25371
- expandTo : 2,
25404
+ expandTo : Number.MAX_SAFE_INTEGER,
25372
25405
  hierarchyQualifier : "OrgChart"
25373
25406
  });
25374
25407
  // code under test (BCP: 2370045709)
25375
25408
  oListBinding.changeParameters({
25376
25409
  $$aggregation : {
25377
- expandTo : 2,
25410
+ expandTo : Number.MAX_SAFE_INTEGER,
25378
25411
  hierarchyQualifier : "OrgChart"
25379
25412
  }
25380
25413
  });
25414
+ assert.strictEqual(oListBinding.getAggregation().expandTo, Number.MAX_SAFE_INTEGER);
25381
25415
  });
25382
25416
  });
25383
25417
  });
@@ -25689,7 +25723,7 @@ sap.ui.define([
25689
25723
  sTeaBusi + "TEAMS('42')/TEAM_2_EMPLOYEES"
25690
25724
  + "?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
25691
25725
  + "HierarchyNodes=$root/TEAMS('42')/TEAM_2_EMPLOYEES"
25692
- + ",HierarchyQualifier='OrgChart',NodeProperty='ID',Levels=999)"
25726
+ + ",HierarchyQualifier='OrgChart',NodeProperty='ID')"
25693
25727
  + "&$select=DistanceFromRoot,DrillState,ID,MANAGER_ID,SALARY/BONUS_CURR"
25694
25728
  + ",SALARY/YEARLY_BONUS_AMOUNT,TEAM_ID",
25695
25729
  "JIRA: CPOUI5ODATAV4-1920, CPOUI5ODATAV4-2275");
@@ -25856,10 +25890,17 @@ sap.ui.define([
25856
25890
  // Additionally ODLB#getDownloadUrl is tested w/ sort.
25857
25891
  // JIRA: CPOUI5ODATAV4-1920
25858
25892
  // BCP: 2370011296
25893
+ //
25894
+ // While the root node 0 (Alpha) is still collapsed, a new root 9 (Aleph) is created and a side
25895
+ // effect for all rows (within the same $batch, JIRA: CPOUI5ODATAV4-2380) turns spliced nodes
25896
+ // into placeholders. Then 0 (Alpha) is expanded again and we scroll down to check that
25897
+ // placeholders still cause proper requests w.r.t. indices.
25898
+ // JIRA: CPOUI5ODATAV4-2355
25859
25899
  QUnit.test("Recursive Hierarchy: expand to 2, collapse & expand root etc.", function (assert) {
25860
25900
  var oCollapsed,
25861
25901
  oListBinding,
25862
25902
  oModel = this.createTeaBusiModel({autoExpandSelect : true}),
25903
+ oNewRoot,
25863
25904
  oRoot,
25864
25905
  oTable,
25865
25906
  sView = '\
@@ -25883,6 +25924,16 @@ sap.ui.define([
25883
25924
  </t:Table>',
25884
25925
  that = this;
25885
25926
 
25927
+ // 9 Aleph (created later)
25928
+ // 0 Alpha
25929
+ // 1 Beta (initially collapsed)
25930
+ // 1.1 Gamma
25931
+ // 1.2 Zeta
25932
+ // 2 Kappa
25933
+ // 3 Lambda
25934
+ // 4 Mu
25935
+ // 5 Xi
25936
+ // ...
25886
25937
  this.expectRequest({
25887
25938
  batchNo : 1,
25888
25939
  url : "EMPLOYEES/$count"
@@ -25959,7 +26010,7 @@ sap.ui.define([
25959
26010
  assert.strictEqual(oListBinding.getDownloadUrl(), sTeaBusi + "EMPLOYEES"
25960
26011
  + "?$apply=orderby(AGE%20desc)"
25961
26012
  + "/com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root/EMPLOYEES"
25962
- + ",HierarchyQualifier='OrgChart',NodeProperty='ID',Levels=999)"
26013
+ + ",HierarchyQualifier='OrgChart',NodeProperty='ID')"
25963
26014
  + "&$select=AGE,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name",
25964
26015
  "JIRA: CPOUI5ODATAV4-1920, CPOUI5ODATAV4-2275");
25965
26016
 
@@ -26026,7 +26077,6 @@ sap.ui.define([
26026
26077
  }) // 204 No Content
26027
26078
  .expectRequest({
26028
26079
  batchNo : 3,
26029
- method : "GET",
26030
26080
  url : "EMPLOYEES?$select=AGE,ID,Name&$filter=ID eq '2'"
26031
26081
  }, {
26032
26082
  value : [{
@@ -26197,6 +26247,136 @@ sap.ui.define([
26197
26247
  ["", "", "", "", "", ""],
26198
26248
  ["", "", "", "", "", ""]
26199
26249
  ]);
26250
+
26251
+ that.expectRequest({
26252
+ batchNo : 6,
26253
+ method : "POST",
26254
+ url : "EMPLOYEES",
26255
+ payload : {
26256
+ // not needed: "EMPLOYEE_2_MANAGER@odata.bind" : null,
26257
+ AGE : 99,
26258
+ Name : "Aleph"
26259
+ }
26260
+ }, {
26261
+ AGE : 199, // side effect
26262
+ ID : "9",
26263
+ MANAGER_ID : null,
26264
+ Name : "Aleph: ℵ" // side effect
26265
+ })
26266
+ .expectRequest({
26267
+ batchNo : 6,
26268
+ url : "EMPLOYEES?$select=AGE,ID&$filter=ID eq '0'"
26269
+ }, {
26270
+ value : [{
26271
+ AGE : 160,
26272
+ ID : "0"
26273
+ }]
26274
+ });
26275
+
26276
+ // code under test (JIRA: CPOUI5ODATAV4-2355)
26277
+ oNewRoot = oListBinding.create({AGE : 99, Name : "Aleph"}, /*bSkipRefresh*/true);
26278
+
26279
+ assert.strictEqual(oNewRoot.getIndex(), 0);
26280
+
26281
+ return Promise.all([
26282
+ oNewRoot.created(),
26283
+ // code under test
26284
+ oListBinding.getHeaderContext().requestSideEffects(["AGE"]),
26285
+ that.waitForChanges(assert, "create new root, side effect: AGE for all rows")
26286
+ ]);
26287
+ }).then(function () {
26288
+ checkTable("new root created, after side effect: AGE for all rows", assert, oTable, [
26289
+ "/EMPLOYEES('9')",
26290
+ "/EMPLOYEES('0')"
26291
+ ], [
26292
+ [undefined, 1, "9", "", "Aleph: ℵ", 199],
26293
+ [false, 1, "0", "", "Alpha", 160],
26294
+ ["", "", "", "", "", ""]
26295
+ ]);
26296
+ assert.strictEqual(oNewRoot.isTransient(), false, "created persisted");
26297
+
26298
+ that.expectRequest("EMPLOYEES?$apply=orderby(AGE desc)"
26299
+ + "/com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root/EMPLOYEES"
26300
+ + ",HierarchyQualifier='OrgChart',NodeProperty='ID',Levels=2)"
26301
+ + "&$select=AGE,DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
26302
+ + "&$filter=not (ID eq '9')&$skip=1&$top=1", {
26303
+ value : [{
26304
+ AGE : 155,
26305
+ DescendantCount : "0", // Edm.Int64
26306
+ DistanceFromRoot : "1", // Edm.Int64
26307
+ DrillState : "collapsed", // Note: overridden by client-side tree state!
26308
+ ID : "1",
26309
+ MANAGER_ID : "0",
26310
+ Name : "Beta"
26311
+ }]
26312
+ });
26313
+
26314
+ // code under test
26315
+ oRoot.expand();
26316
+
26317
+ return that.waitForChanges(assert, "expand 0 (Alpha) again");
26318
+ }).then(function () {
26319
+ checkTable("after expand 0 (Alpha) again", assert, oTable, [
26320
+ "/EMPLOYEES('9')",
26321
+ "/EMPLOYEES('0')",
26322
+ "/EMPLOYEES('1')"
26323
+ ], [
26324
+ [undefined, 1, "9", "", "Aleph: ℵ", 199],
26325
+ [true, 1, "0", "", "Alpha", 160],
26326
+ [true, 2, "1", "0", "Beta", 155]
26327
+ ], 9);
26328
+
26329
+ that.expectRequest("EMPLOYEES"
26330
+ + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '1'),1)"
26331
+ + "/orderby(AGE desc)"
26332
+ + "&$select=AGE,DrillState,ID,MANAGER_ID,Name&$skip=0&$top=2", {
26333
+ value : [{
26334
+ AGE : 141,
26335
+ DrillState : "collapsed",
26336
+ ID : "1.1",
26337
+ MANAGER_ID : "1",
26338
+ Name : "Gamma"
26339
+ }, {
26340
+ AGE : 142,
26341
+ DrillState : "collapsed",
26342
+ ID : "1.2",
26343
+ MANAGER_ID : "1",
26344
+ Name : "Zeta"
26345
+ }]
26346
+ })
26347
+ .expectRequest("EMPLOYEES?$apply=orderby(AGE desc)"
26348
+ + "/com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root/EMPLOYEES"
26349
+ + ",HierarchyQualifier='OrgChart',NodeProperty='ID',Levels=2)"
26350
+ + "&$select=AGE,DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
26351
+ + "&$filter=not (ID eq '9')&$skip=2&$top=1", {
26352
+ value : [{
26353
+ AGE : 166,
26354
+ DescendantCount : "0",
26355
+ DistanceFromRoot : "1",
26356
+ DrillState : "leaf",
26357
+ ID : "2",
26358
+ MANAGER_ID : "0",
26359
+ Name : "Kappa: κ"
26360
+ }]
26361
+ });
26362
+
26363
+ // code under test
26364
+ oTable.setFirstVisibleRow(3);
26365
+
26366
+ return that.waitForChanges(assert, "scroll down");
26367
+ }).then(function () {
26368
+ checkTable("after scroll down", assert, oTable, [
26369
+ "/EMPLOYEES('9')",
26370
+ "/EMPLOYEES('0')",
26371
+ "/EMPLOYEES('1')",
26372
+ "/EMPLOYEES('1.1')",
26373
+ "/EMPLOYEES('1.2')",
26374
+ "/EMPLOYEES('2')"
26375
+ ], [
26376
+ [false, 3, "1.1", "1", "Gamma", 141],
26377
+ [false, 3, "1.2", "1", "Zeta", 142],
26378
+ [undefined, 2, "2", "0", "Kappa: κ", 166]
26379
+ ], 9);
26200
26380
  });
26201
26381
  });
26202
26382
 
@@ -26437,7 +26617,7 @@ sap.ui.define([
26437
26617
  + ",filter(AGE%20ge%200%20and%20(Is_Manager))/search(covfefe),keep%20start)"
26438
26618
  + "/orderby(AGE%20desc)"
26439
26619
  + "/com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root/EMPLOYEES"
26440
- + ",HierarchyQualifier='OrgChart',NodeProperty='ID',Levels=999)"
26620
+ + ",HierarchyQualifier='OrgChart',NodeProperty='ID')"
26441
26621
  + "&$select=DistanceFromRoot,DrillState,ID",
26442
26622
  "JIRA: CPOUI5ODATAV4-1920, CPOUI5ODATAV4-2275");
26443
26623
 
@@ -26476,10 +26656,24 @@ sap.ui.define([
26476
26656
  // initially expanded nodes 1 (Beta) and 0 (Alpha). See that an additional root node becomes
26477
26657
  // visible!
26478
26658
  // JIRA: CPOUI5ODATAV4-1743
26659
+ //
26660
+ // Create new child and cancel immediately via deletion (JIRA: CPOUI5ODATAV4-2359)
26661
+ //
26662
+ // While the root node 0 (Alpha) is still collapsed, a new root (Beth) is created; a side effect
26663
+ // for all rows turns spliced nodes into placeholders, then 0 (Alpha) is expanded again to check
26664
+ // that placeholders still cause proper requests w.r.t. indices.
26665
+ // JIRA: CPOUI5ODATAV4-2355
26666
+ //
26667
+ // A new child (Gimel) for 0 (Alpha) is created, then 0 (Alpha) is collapsed again to check
26668
+ // that the internal "limited descendant count" has been updated correctly. Finally, 0 (Alpha)
26669
+ // is expanded again to check that internal "index" handling is correct.
26670
+ // JIRA: CPOUI5ODATAV4-2359
26479
26671
  QUnit.test("Recursive Hierarchy: collapse nested initially expanded nodes", function (assert) {
26480
26672
  var oAlpha,
26481
26673
  oBeta,
26482
26674
  oModel = this.createTeaBusiModel({autoExpandSelect : true}),
26675
+ oNewChild,
26676
+ oNewRoot,
26483
26677
  oTable,
26484
26678
  sView = '\
26485
26679
  <t:Table id="table" rows="{path : \'/EMPLOYEES\',\
@@ -26498,7 +26692,9 @@ sap.ui.define([
26498
26692
  </t:Table>',
26499
26693
  that = this;
26500
26694
 
26695
+ // B Beth (created later)
26501
26696
  // 0 Alpha
26697
+ // C Gimel (created later)
26502
26698
  // 1 Beta
26503
26699
  // 1.1 Gamma
26504
26700
  // 1.2 Zeta
@@ -26579,6 +26775,13 @@ sap.ui.define([
26579
26775
  [undefined, 2, "2", "0", "Kappa", 56]
26580
26776
  ], 11);
26581
26777
 
26778
+ // code under test (JIRA: CPOUI5ODATAV4-2359)
26779
+ const oLostChild = oAlpha.getBinding().create({
26780
+ "@$ui5.node.parent" : oAlpha,
26781
+ Name : "n/a"
26782
+ }, /*bSkipRefresh*/true);
26783
+ const oDeletePromise = oLostChild.delete();
26784
+
26582
26785
  that.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
26583
26786
  + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
26584
26787
  + ",NodeProperty='ID',Levels=3)"
@@ -26605,7 +26808,11 @@ sap.ui.define([
26605
26808
 
26606
26809
  oBeta.collapse();
26607
26810
 
26608
- return that.waitForChanges(assert, "collapse 1 (Beta)");
26811
+ return Promise.all([
26812
+ checkCanceled(assert, oLostChild.created()),
26813
+ oDeletePromise,
26814
+ that.waitForChanges(assert, "collapse 1 (Beta)")
26815
+ ]);
26609
26816
  }).then(function () {
26610
26817
  checkTable("after collapse 1 (Beta) ", assert, oTable, [
26611
26818
  "/EMPLOYEES('0')",
@@ -26641,7 +26848,7 @@ sap.ui.define([
26641
26848
 
26642
26849
  return that.waitForChanges(assert, "collapse 0 (Alpha)");
26643
26850
  }).then(function () {
26644
- checkTable("after collapse 0 (Alpha) ", assert, oTable, [
26851
+ checkTable("after collapse 0 (Alpha)", assert, oTable, [
26645
26852
  "/EMPLOYEES('0')",
26646
26853
  "/EMPLOYEES('9')"
26647
26854
  ], [
@@ -26651,6 +26858,233 @@ sap.ui.define([
26651
26858
  ["", "", "", "", "", ""],
26652
26859
  ["", "", "", "", "", ""]
26653
26860
  ], 2);
26861
+ const oAleph = oTable.getRows()[1].getBindingContext();
26862
+
26863
+ // code under test
26864
+ assert.strictEqual(oAlpha.isAncestorOf(oAleph), false, "JIRA: CPOUI5ODATAV4-2337");
26865
+ assert.strictEqual(oAleph.isAncestorOf(oAlpha), false, "JIRA: CPOUI5ODATAV4-2337");
26866
+
26867
+ that.expectRequest({
26868
+ method : "POST",
26869
+ url : "EMPLOYEES",
26870
+ payload : {
26871
+ // not needed: "EMPLOYEE_2_MANAGER@odata.bind" : null,
26872
+ Name : "Beth"
26873
+ }
26874
+ }, {
26875
+ AGE : 70,
26876
+ ID : "B",
26877
+ MANAGER_ID : null,
26878
+ Name : "Beth, not Beta" // side effect
26879
+ });
26880
+
26881
+ // code under test (JIRA: CPOUI5ODATAV4-2355)
26882
+ oNewRoot = oAlpha.getBinding().create({Name : "Beth"}, /*bSkipRefresh*/true);
26883
+
26884
+ assert.strictEqual(oNewRoot.getIndex(), 0);
26885
+
26886
+ return Promise.all([
26887
+ oNewRoot.created(),
26888
+ that.waitForChanges(assert, "create new root")
26889
+ ]);
26890
+ }).then(function () {
26891
+ checkTable("after create new root", assert, oTable, [
26892
+ "/EMPLOYEES('B')",
26893
+ "/EMPLOYEES('0')",
26894
+ "/EMPLOYEES('9')"
26895
+ ], [
26896
+ [undefined, 1, "B", "", "Beth, not Beta", 70],
26897
+ [false, 1, "0", "", "Alpha", 60],
26898
+ [undefined, 1, "9", "", "Aleph", 69],
26899
+ ["", "", "", "", "", ""],
26900
+ ["", "", "", "", "", ""]
26901
+ ]);
26902
+ assert.strictEqual(oNewRoot.isTransient(), false, "created persisted");
26903
+
26904
+ that.expectRequest("EMPLOYEES?$select=AGE,ID"
26905
+ + "&$filter=ID eq 'B' or ID eq '0' or ID eq '9'&$top=3", {
26906
+ value : [{
26907
+ AGE : 170,
26908
+ ID : "B" // Beth
26909
+ }, {
26910
+ AGE : 160,
26911
+ ID : "0" // Alpha
26912
+ }, {
26913
+ AGE : 169,
26914
+ ID : "9" // Aleph
26915
+ }]
26916
+ });
26917
+
26918
+ return Promise.all([
26919
+ // code under test
26920
+ oAlpha.getBinding().getHeaderContext().requestSideEffects(["AGE"]),
26921
+ that.waitForChanges(assert, "side effect: AGE for all rows")
26922
+ ]);
26923
+ }).then(function () {
26924
+ checkTable("after side effect: AGE for all rows", assert, oTable, [
26925
+ "/EMPLOYEES('B')",
26926
+ "/EMPLOYEES('0')",
26927
+ "/EMPLOYEES('9')"
26928
+ ], [
26929
+ [undefined, 1, "B", "", "Beth, not Beta", 170],
26930
+ [false, 1, "0", "", "Alpha", 160],
26931
+ [undefined, 1, "9", "", "Aleph", 169],
26932
+ ["", "", "", "", "", ""],
26933
+ ["", "", "", "", "", ""]
26934
+ ]);
26935
+
26936
+ that.expectRequest({batchNo : 6,
26937
+ url : "EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
26938
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
26939
+ + ",NodeProperty='ID',Levels=3)"
26940
+ + "&$select=AGE,DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
26941
+ + "&$filter=not (ID eq 'B')&$skip=1&$top=1"}, {
26942
+ value : [{
26943
+ AGE : 155,
26944
+ DescendantCount : "2",
26945
+ DistanceFromRoot : "1",
26946
+ DrillState : "expanded", // Note: overridden by client-side tree state!
26947
+ ID : "1",
26948
+ MANAGER_ID : "0",
26949
+ Name : "Beta"
26950
+ }]
26951
+ })
26952
+ .expectRequest({batchNo : 6,
26953
+ url : "EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
26954
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
26955
+ + ",NodeProperty='ID',Levels=3)"
26956
+ + "&$select=AGE,DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
26957
+ + "&$filter=not (ID eq 'B')&$skip=4&$top=2"}, {
26958
+ value : [{
26959
+ AGE : 156,
26960
+ DescendantCount : "0",
26961
+ DistanceFromRoot : "1",
26962
+ DrillState : "leaf",
26963
+ ID : "2",
26964
+ MANAGER_ID : "0",
26965
+ Name : "Kappa"
26966
+ }, {
26967
+ AGE : 157,
26968
+ DescendantCount : "0",
26969
+ DistanceFromRoot : "1",
26970
+ DrillState : "leaf",
26971
+ ID : "3",
26972
+ MANAGER_ID : "0",
26973
+ Name : "Lambda"
26974
+ }]
26975
+ });
26976
+
26977
+ // code under test
26978
+ oAlpha.expand();
26979
+
26980
+ return that.waitForChanges(assert, "expand 0 (Alpha)");
26981
+ }).then(function () {
26982
+ checkTable("after expand 0 (Alpha)", assert, oTable, [
26983
+ "/EMPLOYEES('B')",
26984
+ "/EMPLOYEES('0')",
26985
+ "/EMPLOYEES('1')",
26986
+ "/EMPLOYEES('2')",
26987
+ "/EMPLOYEES('3')",
26988
+ "/EMPLOYEES('9')"
26989
+ ], [
26990
+ [undefined, 1, "B", "", "Beth, not Beta", 170],
26991
+ [true, 1, "0", "", "Alpha", 160],
26992
+ [false, 2, "1", "0", "Beta", 155],
26993
+ [undefined, 2, "2", "0", "Kappa", 156],
26994
+ [undefined, 2, "3", "0", "Lambda", 157]
26995
+ ], 10);
26996
+
26997
+ that.expectRequest({
26998
+ method : "POST",
26999
+ url : "EMPLOYEES",
27000
+ payload : {
27001
+ "EMPLOYEE_2_MANAGER@odata.bind" : "EMPLOYEES('0')",
27002
+ Name : "gIMEL"
27003
+ }
27004
+ }, {
27005
+ AGE : 180,
27006
+ ID : "C",
27007
+ MANAGER_ID : "0", // side effect
27008
+ Name : "Gimel" // side effect
27009
+ });
27010
+
27011
+ // code under test (JIRA: CPOUI5ODATAV4-2359)
27012
+ oNewChild = oAlpha.getBinding().create({
27013
+ "@$ui5.node.parent" : oAlpha,
27014
+ Name : "gIMEL"
27015
+ }, /*bSkipRefresh*/true);
27016
+
27017
+ assert.strictEqual(oNewChild.getIndex(), 2);
27018
+ assert.strictEqual(oNewChild.getProperty("@$ui5.node.level"), 2);
27019
+ assert.deepEqual(oNewChild.getObject(), {
27020
+ "@$ui5.context.isTransient" : true,
27021
+ "@$ui5.node.level" : 2,
27022
+ // "@$ui5.node.parent" : oAlpha, // removed by #create
27023
+ Name : "gIMEL"
27024
+ });
27025
+
27026
+ return Promise.all([
27027
+ oNewChild.created(),
27028
+ that.waitForChanges(assert, "create new child beneath 0 (Alpha)")
27029
+ ]);
27030
+ }).then(function () {
27031
+ checkTable("after create new child beneath 0 (Alpha)", assert, oTable, [
27032
+ "/EMPLOYEES('B')",
27033
+ "/EMPLOYEES('0')",
27034
+ "/EMPLOYEES('C')",
27035
+ "/EMPLOYEES('1')",
27036
+ "/EMPLOYEES('2')",
27037
+ "/EMPLOYEES('3')",
27038
+ "/EMPLOYEES('9')"
27039
+ ], [
27040
+ [undefined, 1, "B", "", "Beth, not Beta", 170],
27041
+ [true, 1, "0", "", "Alpha", 160],
27042
+ [undefined, 2, "C", "0", "Gimel", 180],
27043
+ [false, 2, "1", "0", "Beta", 155],
27044
+ [undefined, 2, "2", "0", "Kappa", 156]
27045
+ ], 11);
27046
+ assert.strictEqual(oNewChild.isTransient(), false, "created persisted");
27047
+
27048
+ // code under test
27049
+ oAlpha.collapse();
27050
+
27051
+ return that.waitForChanges(assert, "collapse 0 (Alpha) again");
27052
+ }).then(function () {
27053
+ checkTable("after collapse 0 (Alpha) again", assert, oTable, [
27054
+ "/EMPLOYEES('B')",
27055
+ "/EMPLOYEES('0')",
27056
+ "/EMPLOYEES('9')"
27057
+ ], [
27058
+ [undefined, 1, "B", "", "Beth, not Beta", 170],
27059
+ [false, 1, "0", "", "Alpha", 160],
27060
+ [undefined, 1, "9", "", "Aleph", 169],
27061
+ ["", "", "", "", "", ""],
27062
+ ["", "", "", "", "", ""]
27063
+ ]);
27064
+
27065
+ // code under test
27066
+ oAlpha.expand();
27067
+
27068
+ return that.waitForChanges(assert, "expand 0 (Alpha) again");
27069
+ }).then(function () {
27070
+ checkTable("after create new child beneath 0 (Alpha)", assert, oTable, [
27071
+ "/EMPLOYEES('B')",
27072
+ "/EMPLOYEES('0')",
27073
+ "/EMPLOYEES('C')",
27074
+ "/EMPLOYEES('1')",
27075
+ "/EMPLOYEES('2')",
27076
+ "/EMPLOYEES('3')",
27077
+ "/EMPLOYEES('9')"
27078
+ ], [
27079
+ [undefined, 1, "B", "", "Beth, not Beta", 170],
27080
+ [true, 1, "0", "", "Alpha", 160],
27081
+ [undefined, 2, "C", "0", "Gimel", 180],
27082
+ [false, 2, "1", "0", "Beta", 155],
27083
+ [undefined, 2, "2", "0", "Kappa", 156]
27084
+ ], 11);
27085
+ assert.strictEqual(oNewChild.getBinding().getCurrentContexts()[2], oNewChild,
27086
+ "still the same");
27087
+ assert.strictEqual(oNewChild.isTransient(), false, "created persisted");
26654
27088
  });
26655
27089
  });
26656
27090
 
@@ -27710,8 +28144,8 @@ sap.ui.define([
27710
28144
  });
27711
28145
 
27712
28146
  //*********************************************************************************************
27713
- // Scenario: Deferred delete and reinsert of a top-level node in a recursive hierarchy. Only
27714
- // one node, so that the parent would have to become a leaf if there were one.
28147
+ // Scenario: Delete a top-level node in a recursive hierarchy. The binding has only one node, so
28148
+ // that the parent would have to become a leaf if there was one.
27715
28149
  // JIRA: CPOUI5ODATAV4-2224
27716
28150
  QUnit.test("Recursive Hierarchy: delete top-level", async function (assert) {
27717
28151
  const oModel = this.createTeaBusiModel({autoExpandSelect : true});
@@ -27726,9 +28160,9 @@ sap.ui.define([
27726
28160
  <Text id="name" text="{Name}"/>
27727
28161
  </Table>`;
27728
28162
 
27729
- this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels"
27730
- + "(HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart',NodeProperty='ID'"
27731
- + ",Levels=1)"
28163
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
28164
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
28165
+ + ",NodeProperty='ID',Levels=1)"
27732
28166
  + "&$select=DrillState,ID,Name&$count=true&$skip=0&$top=100", {
27733
28167
  "@odata.count" : "1",
27734
28168
  value : [{
@@ -27741,42 +28175,27 @@ sap.ui.define([
27741
28175
  await this.createView(assert, sView, oModel);
27742
28176
 
27743
28177
  const oTable = this.oView.byId("table");
27744
- const oAlpha = oTable.getItems()[0].getBindingContext();
27745
- // code under test
27746
- const oDeletePromise = oAlpha.delete("doNotSubmit");
27747
-
27748
- await resolveLater(); // no observable changes
27749
-
27750
- checkTable("after delete", assert, oTable, [], [], 0);
27751
-
27752
- this.expectCanceledError("Failed to delete /EMPLOYEES('0')",
27753
- "Request canceled: DELETE EMPLOYEES('0'); group: doNotSubmit")
27754
- .expectChange("name", ["Alpha"]);
27755
-
27756
- // code under test
27757
- oAlpha.resetChanges();
28178
+ this.expectRequest("DELETE EMPLOYEES('0')");
27758
28179
 
27759
28180
  await Promise.all([
27760
- checkCanceled(assert, oDeletePromise),
27761
- this.waitForChanges(assert, "cancel delete")
28181
+ oTable.getItems()[0].getBindingContext().delete(), // code under test
28182
+ this.waitForChanges(assert, "delete")
27762
28183
  ]);
27763
28184
 
27764
- checkTable("after reinsert", assert, oTable, ["/EMPLOYEES('0')"], [
27765
- ["0", "Alpha"]
27766
- ], 1);
28185
+ checkTable("after delete", assert, oTable, [], [], 0);
27767
28186
  });
27768
28187
 
27769
28188
  //*********************************************************************************************
27770
- // Scenario: Deferred delete of Gamma, a leaf in a recursive hierarchy which is not the only
27771
- // child of its parent. Before the delete ensure that there are two invisible elements (Delta,
27772
- // Epsilon). See that Gamma is deleted on the UI immediately. Request side effects so that
27773
- // Epsilon is removed again. Scroll down to see that Epsilon and Zeta are requested correctly.
27774
- // Cancel the delete and check that Gamma is restored correcty. Scroll down to the end to see
27775
- // that Eta and Theta are requested correctly.
28189
+ // Scenario: Delete Gamma, a leaf in a recursive hierarchy which is not the only child of its
28190
+ // parent. Before the delete ensure that there are two invisible elements (Delta, Epsilon).
28191
+ // Request side effects so that Epsilon is removed again. Scroll down to see that Epsilon and
28192
+ // Zeta are requested correctly. Scroll down to the end to see that Eta and Theta are requested
28193
+ // correctly.
27776
28194
  // ("Pi" is attached to a name when it is read a second time.)
27777
28195
  // JIRA: CPOUI5ODATAV4-2224
28196
+ // JIRA: CPOUI5ODATAV4-2345
27778
28197
  QUnit.test("Recursive Hierarchy: delete second leaf", function (assert) {
27779
- var oDeletePromise, oGamma, oTable;
28198
+ var oTable;
27780
28199
 
27781
28200
  const oModel = this.createTeaBusiModel({autoExpandSelect : true});
27782
28201
  const sView = `
@@ -27798,13 +28217,13 @@ sap.ui.define([
27798
28217
  // 1 Beta
27799
28218
  // 2 Gamma (deleted)
27800
28219
  // 3 Delta (read via expand, comes into view due to delete)
27801
- // 4 Epsilon (exists hidden during delete, then dropped and read again via paging)
28220
+ // 4 Epsilon (exists hidden when deleting, then dropped and read again via paging)
27802
28221
  // 5 Zeta (read via paging after delete)
27803
- // 6 Eta (read via paging after reset)
28222
+ // 6 Eta (read via paging after delete)
27804
28223
  // 7 Theta
27805
- this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels"
27806
- + "(HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart',NodeProperty='ID'"
27807
- + ",Levels=1)"
28224
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
28225
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
28226
+ + ",NodeProperty='ID',Levels=1)"
27808
28227
  + "&$select=DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=3", {
27809
28228
  "@odata.count" : "2",
27810
28229
  value : [{
@@ -27888,13 +28307,13 @@ sap.ui.define([
27888
28307
  [undefined, 2, "2", "0", "Gamma"]
27889
28308
  ], 8);
27890
28309
 
27891
- that.expectChange("name", [,, "Delta"]);
27892
-
27893
- oGamma = oTable.getRows()[2].getBindingContext();
27894
- // code under test
27895
- oDeletePromise = oGamma.delete("doNotSubmit");
28310
+ that.expectRequest("DELETE EMPLOYEES('2')")
28311
+ .expectChange("name", [,, "Delta"]);
27896
28312
 
27897
- return that.waitForChanges(assert, "delete");
28313
+ return Promise.all([
28314
+ oTable.getRows()[2].getBindingContext().delete(), // code under test
28315
+ that.waitForChanges(assert, "delete")
28316
+ ]);
27898
28317
  }).then(function () {
27899
28318
  checkTable("after delete", assert, oTable, [
27900
28319
  "/EMPLOYEES('0')",
@@ -27925,14 +28344,13 @@ sap.ui.define([
27925
28344
 
27926
28345
  return Promise.all([
27927
28346
  // code under test
27928
- oGamma.getBinding().getHeaderContext().requestSideEffects(["Name"]),
28347
+ oTable.getBinding("rows").getHeaderContext().requestSideEffects(["Name"]),
27929
28348
  that.waitForChanges(assert, "side effects")
27930
28349
  ]);
27931
28350
  }).then(function () {
27932
28351
  that.expectRequest("EMPLOYEES"
27933
28352
  + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '0'),1)"
27934
- + "&$select=DrillState,ID,MANAGER_ID,Name&$filter=not (ID eq '2')"
27935
- + "&$skip=2&$top=2", {
28353
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$skip=2&$top=2", {
27936
28354
  "@odata.count" : "5",
27937
28355
  value : [{
27938
28356
  DrillState : "leaf",
@@ -27951,45 +28369,11 @@ sap.ui.define([
27951
28369
  // code under test
27952
28370
  oTable.setFirstVisibleRow(2);
27953
28371
 
27954
- return that.waitForChanges(assert, "scroll while deleted");
27955
- }).then(function () {
27956
- checkTable("after scroll while deleted", assert, oTable, [
27957
- "/EMPLOYEES('0')",
27958
- "/EMPLOYEES('1')",
27959
- "/EMPLOYEES('3')",
27960
- "/EMPLOYEES('4')",
27961
- "/EMPLOYEES('5')"
27962
- ], [
27963
- [undefined, 2, "3", "0", "Delta Pi"],
27964
- [undefined, 2, "4", "0", "Epsilon Pi"],
27965
- [false, 2, "5", "0", "Zeta"]
27966
- ], 7);
27967
-
27968
- that.expectCanceledError("Failed to delete /EMPLOYEES('2')",
27969
- "Request canceled: DELETE EMPLOYEES('2'); group: doNotSubmit")
27970
- .expectChange("name", [,, "Gamma", "Delta Pi", "Epsilon Pi", "Zeta"]);
27971
-
27972
- // code under test
27973
- oGamma.resetChanges();
27974
-
27975
- return checkCanceled(assert, oDeletePromise);
28372
+ return that.waitForChanges(assert, "scroll after delete");
27976
28373
  }).then(function () {
27977
- checkTable("after reset", assert, oTable, [
27978
- "/EMPLOYEES('0')",
27979
- "/EMPLOYEES('1')",
27980
- "/EMPLOYEES('2')",
27981
- "/EMPLOYEES('3')",
27982
- "/EMPLOYEES('4')",
27983
- "/EMPLOYEES('5')"
27984
- ], [
27985
- [undefined, 2, "2", "0", "Gamma"],
27986
- [undefined, 2, "3", "0", "Delta Pi"],
27987
- [undefined, 2, "4", "0", "Epsilon Pi"]
27988
- ], 8);
27989
-
27990
28374
  that.expectRequest("EMPLOYEES"
27991
28375
  + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '0'),1)"
27992
- + "&$select=DrillState,ID,MANAGER_ID,Name&$skip=5&$top=1", {
28376
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$skip=4&$top=1", {
27993
28377
  value : [{
27994
28378
  DrillState : "collapsed",
27995
28379
  ID : "6",
@@ -28008,17 +28392,16 @@ sap.ui.define([
28008
28392
  Name : "Theta Pi"
28009
28393
  }]
28010
28394
  })
28011
- .expectChange("name", [,,,,,, "Eta", "Theta Pi"]);
28395
+ .expectChange("name", [,,,, "Zeta", "Eta", "Theta Pi"]);
28012
28396
 
28013
28397
  // code under test
28014
- oTable.setFirstVisibleRow(5);
28398
+ oTable.setFirstVisibleRow(4);
28015
28399
 
28016
28400
  return that.waitForChanges(assert, "scroll to bottom");
28017
28401
  }).then(function () {
28018
28402
  checkTable("after scroll to bottom", assert, oTable, [
28019
28403
  "/EMPLOYEES('0')",
28020
28404
  "/EMPLOYEES('1')",
28021
- "/EMPLOYEES('2')",
28022
28405
  "/EMPLOYEES('3')",
28023
28406
  "/EMPLOYEES('4')",
28024
28407
  "/EMPLOYEES('5')",
@@ -28028,24 +28411,24 @@ sap.ui.define([
28028
28411
  [false, 2, "5", "0", "Zeta"],
28029
28412
  [false, 2, "6", "0", "Eta"],
28030
28413
  [false, 1, "7", "", "Theta Pi"]
28031
- ], 8);
28414
+ ], 7);
28032
28415
  });
28033
28416
  });
28034
28417
 
28035
28418
  //*********************************************************************************************
28036
- // Scenario: Deferred delete of a non-leaf node with loaded children in a recursive hierarchy
28037
- // which is the only child of its parent. Two variants: delete while collapsed and while
28038
- // expanded.
28419
+ // Scenario: Delete a non-leaf node with loaded children in a recursive hierarchy which is the
28420
+ // only child of its parent. Two variants: delete while collapsed and while expanded.
28039
28421
  // * Expand Alpha and Beta.
28040
28422
  // * Collapse Beta (in variant 1).
28041
- // * Delete Beta in an API group. See that Alpha becomes a leaf.
28042
- // * Cancel the delete.
28043
- // * Expand Beta without a further request (in variant 1).
28044
- // * See that Alpha is expanded, and that Gamma is shown again.
28423
+ // * Delete Beta and let the request fail. See that it is expanded again in variant 2.
28424
+ // * Delete Beta again. See that Alpha becomes a leaf.
28045
28425
  // JIRA: CPOUI5ODATAV4-2224
28426
+ // JIRA: CPOUI5ODATAV4-2345
28046
28427
  [false, true].forEach(function (bExpanded) {
28047
28428
  const sState = bExpanded ? "expanded" : "collapsed";
28048
28429
  QUnit.test(`Recursive Hierarchy: delete single ${sState} child`, async function (assert) {
28430
+ var oTable;
28431
+
28049
28432
  const oModel = this.createTeaBusiModel({autoExpandSelect : true});
28050
28433
  const sView = `
28051
28434
  <Table id="table" items="{path : '/EMPLOYEES',
@@ -28061,9 +28444,35 @@ sap.ui.define([
28061
28444
  <Text id="name" text="{Name}"/>
28062
28445
  </Table>`;
28063
28446
 
28447
+ function expectTable(sTitle, bExpanded) {
28448
+ if (bExpanded) {
28449
+ checkTable(sTitle, assert, oTable, [
28450
+ "/EMPLOYEES('0')",
28451
+ "/EMPLOYEES('1')",
28452
+ "/EMPLOYEES('2')",
28453
+ "/EMPLOYEES('3')"
28454
+ ], [
28455
+ [true, 1, "0", "", "Alpha"],
28456
+ [true, 2, "1", "0", "Beta"],
28457
+ [false, 3, "2", "1", "Gamma"],
28458
+ [false, 1, "3", "", "Delta"]
28459
+ ], 4);
28460
+ } else {
28461
+ checkTable(sTitle, assert, oTable, [
28462
+ "/EMPLOYEES('0')",
28463
+ "/EMPLOYEES('1')",
28464
+ "/EMPLOYEES('3')"
28465
+ ], [
28466
+ [true, 1, "0", "", "Alpha"],
28467
+ [false, 2, "1", "0", "Beta"],
28468
+ [false, 1, "3", "", "Delta"]
28469
+ ], 3);
28470
+ }
28471
+ }
28472
+
28064
28473
  // 0 Alpha
28065
28474
  // 1 Beta (deleted while Gamma is loaded)
28066
- // 2 Gamma (must not get lost)
28475
+ // 2 Gamma (allows expanding Beta)
28067
28476
  // 3 Delta (only helps with the eventing)
28068
28477
  this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels"
28069
28478
  + "(HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart',NodeProperty='ID'"
@@ -28101,7 +28510,7 @@ sap.ui.define([
28101
28510
  .expectChange("expanded", [true,, false])
28102
28511
  .expectChange("name", [, "Beta", "Delta"]);
28103
28512
 
28104
- const oTable = this.oView.byId("table");
28513
+ oTable = this.oView.byId("table");
28105
28514
  oTable.getItems()[0].getBindingContext().expand();
28106
28515
 
28107
28516
  await this.waitForChanges(assert, "expand Alpha");
@@ -28125,20 +28534,11 @@ sap.ui.define([
28125
28534
 
28126
28535
  await this.waitForChanges(assert, "expand Beta");
28127
28536
 
28128
- checkTable("after expand", assert, oTable, [
28129
- "/EMPLOYEES('0')",
28130
- "/EMPLOYEES('1')",
28131
- "/EMPLOYEES('2')",
28132
- "/EMPLOYEES('3')"
28133
- ], [
28134
- [true, 1, "0", "", "Alpha"],
28135
- [true, 2, "1", "0", "Beta"],
28136
- [false, 3, "2", "1", "Gamma"],
28137
- [false, 1, "3", "", "Delta"]
28138
- ], 4);
28537
+ expectTable("after expand", true);
28139
28538
 
28140
28539
  if (bExpanded) {
28141
- this.expectChange("expanded", [, false]); // Beta is collapsed before being deleted
28540
+ this.expectChange("expanded", [, false]) // Beta is collapsed before being deleted
28541
+ .expectChange("expanded", [, true]); // ...and expanded again after the error
28142
28542
  } else {
28143
28543
  this.expectChange("expanded", [, false])
28144
28544
  .expectChange("name", [,, "Delta"]);
@@ -28147,24 +28547,38 @@ sap.ui.define([
28147
28547
 
28148
28548
  await this.waitForChanges(assert, "collapse Beta");
28149
28549
 
28150
- checkTable("after collapse", assert, oTable, [
28151
- "/EMPLOYEES('0')",
28152
- "/EMPLOYEES('1')",
28153
- "/EMPLOYEES('3')"
28154
- ], [
28155
- [true, 1, "0", "", "Alpha"],
28156
- [false, 2, "1", "0", "Beta"],
28157
- [false, 1, "3", "", "Delta"]
28158
- ], 3);
28550
+ expectTable("after collapse", false);
28159
28551
  }
28160
28552
 
28161
- this.expectChange("expanded", [undefined]) // Alpha is now a leaf
28162
- .expectChange("name", [, "Delta"]);
28553
+ this.oLogMock.expects("error").withArgs("Failed to delete /EMPLOYEES('1')");
28554
+ this.expectRequest("DELETE EMPLOYEES('1')", createErrorInsideBatch())
28555
+ .expectMessages([{
28556
+ code : "CODE",
28557
+ message : "Request intentionally failed",
28558
+ persistent : true,
28559
+ technical : true,
28560
+ type : "Error"
28561
+ }]);
28163
28562
 
28164
- // code under test
28165
- const oDeletePromise = oBeta.delete("doNotSubmit");
28563
+ await Promise.all([
28564
+ // code under test
28565
+ oBeta.delete().then(mustFail(assert), function (_oError) {}),
28566
+ this.waitForChanges(assert, "failing to delete Beta")
28567
+ ]);
28568
+
28569
+ expectTable("after failed delete", bExpanded);
28570
+
28571
+ if (bExpanded) {
28572
+ this.expectChange("expanded", [, false]); // Beta is collapsed before being deleted
28573
+ }
28574
+ this.expectRequest("DELETE EMPLOYEES('1')")
28575
+ .expectChange("expanded", [undefined]) // Alpha is now a leaf
28576
+ .expectChange("name", [, "Delta"]);
28166
28577
 
28167
- await this.waitForChanges(assert, "delete Beta");
28578
+ await Promise.all([
28579
+ oBeta.delete(), // code under test
28580
+ this.waitForChanges(assert, "delete Beta")
28581
+ ]);
28168
28582
 
28169
28583
  checkTable("after delete", assert, oTable, [
28170
28584
  "/EMPLOYEES('0')",
@@ -28173,47 +28587,176 @@ sap.ui.define([
28173
28587
  [undefined, 1, "0", "", "Alpha"], // now a leaf
28174
28588
  [false, 1, "3", "", "Delta"]
28175
28589
  ], 2);
28590
+ });
28591
+ });
28176
28592
 
28177
- this.expectCanceledError("Failed to delete /EMPLOYEES('1')",
28178
- "Request canceled: DELETE EMPLOYEES('1'); group: doNotSubmit");
28179
- if (bExpanded) {
28180
- // Alpha is expanded again, Beta is expanded after being restored
28181
- this.expectChange("expanded", [true, true, false, false])
28182
- .expectChange("name", [, "Beta", "Gamma", "Delta"]);
28183
- } else {
28184
- this.expectChange("expanded", [true,, false]) // Alpha is expanded again
28185
- .expectChange("name", [, "Beta", "Delta"]);
28186
- }
28593
+ //*********************************************************************************************
28594
+ // Scenario: Delete multiple nodes in a recursive hierarchy
28595
+ // JIRA: CPOUI5ODATAV4-2302
28596
+ QUnit.test("Recursive Hierarchy: delete multiple nodes", async function (assert) {
28597
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
28598
+ const sView = `
28599
+ <Table id="table" items="{path : '/EMPLOYEES',
28600
+ parameters : {
28601
+ $$aggregation : {
28602
+ hierarchyQualifier : 'OrgChart'
28603
+ }
28604
+ }}">
28605
+ <Text text="{= %{@$ui5.node.isExpanded} }"/>
28606
+ <Text text="{= %{@$ui5.node.level} }"/>
28607
+ <Text text="{ID}"/>
28608
+ <Text text="{MANAGER_ID}"/>
28609
+ <Text text="{Name}"/>
28610
+ </Table>`;
28187
28611
 
28188
- // code under test
28189
- oBeta.resetChanges();
28612
+ // 0 Alpha
28613
+ // 1 Beta (deleted)
28614
+ // 2 Gamma (deleted)
28615
+ // 3 Delta
28616
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels"
28617
+ + "(HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart',NodeProperty='ID'"
28618
+ + ",Levels=1)"
28619
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=100", {
28620
+ "@odata.count" : "1",
28621
+ value : [{
28622
+ DrillState : "collapsed",
28623
+ ID : "0",
28624
+ MANAGER_ID : null,
28625
+ Name : "Alpha"
28626
+ }]
28627
+ });
28628
+
28629
+ await this.createView(assert, sView, oModel);
28630
+
28631
+ this.expectRequest("EMPLOYEES"
28632
+ + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '0'),1)"
28633
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=100", {
28634
+ "@odata.count" : "3",
28635
+ value : [{
28636
+ DrillState : "leaf",
28637
+ ID : "1",
28638
+ MANAGER_ID : "0",
28639
+ Name : "Beta"
28640
+ }, {
28641
+ DrillState : "leaf",
28642
+ ID : "2",
28643
+ MANAGER_ID : "0",
28644
+ Name : "Gamma"
28645
+ }, {
28646
+ DrillState : "leaf",
28647
+ ID : "3",
28648
+ MANAGER_ID : "0",
28649
+ Name : "Delta"
28650
+ }]
28651
+ });
28652
+
28653
+ const oTable = this.oView.byId("table");
28654
+ oTable.getItems()[0].getBindingContext().expand();
28655
+
28656
+ await this.waitForChanges(assert, "expand Alpha");
28657
+
28658
+ checkTable("after expand Alpha", assert, oTable, [
28659
+ "/EMPLOYEES('0')",
28660
+ "/EMPLOYEES('1')",
28661
+ "/EMPLOYEES('2')",
28662
+ "/EMPLOYEES('3')"
28663
+ ], [
28664
+ [true, 1, "0", "", "Alpha"],
28665
+ [undefined, 2, "1", "0", "Beta"],
28666
+ [undefined, 2, "2", "0", "Gamma"],
28667
+ [undefined, 2, "3", "0", "Delta"]
28668
+ ]);
28669
+
28670
+ this.expectRequest("DELETE EMPLOYEES('1')")
28671
+ .expectRequest("DELETE EMPLOYEES('2')");
28190
28672
 
28191
28673
  await Promise.all([
28192
- checkCanceled(assert, oDeletePromise),
28193
- this.waitForChanges(assert, "cancel")
28674
+ // code under test
28675
+ oTable.getItems()[1].getBindingContext().delete(),
28676
+ oTable.getItems()[2].getBindingContext().delete(),
28677
+ this.waitForChanges(assert, "delete Beta and Gamma")
28194
28678
  ]);
28195
28679
 
28196
- if (!bExpanded) {
28197
- checkTable("after reset", assert, oTable, [
28198
- "/EMPLOYEES('0')",
28199
- "/EMPLOYEES('1')",
28200
- "/EMPLOYEES('3')"
28201
- ], [
28202
- [true, 1, "0", "", "Alpha"], // expanded again
28203
- [false, 2, "1", "0", "Beta"],
28204
- [false, 1, "3", "", "Delta"]
28205
- ], 3);
28680
+ checkTable("after delete", assert, oTable, [
28681
+ "/EMPLOYEES('0')",
28682
+ "/EMPLOYEES('3')"
28683
+ ], [
28684
+ [true, 1, "0", "", "Alpha"],
28685
+ [undefined, 2, "3", "0", "Delta"]
28686
+ ]);
28687
+ });
28206
28688
 
28207
- this.expectChange("expanded", [, true, , false])
28208
- .expectChange("name", [, , "Gamma", "Delta"]);
28689
+ //*********************************************************************************************
28690
+ // Scenario: Delete a non-leaf node with descendants loaded partially via expandTo in a
28691
+ // recursive hierarchy which is the only child of its parent.
28692
+ //
28693
+ // JIRA: CPOUI5ODATAV4-2302
28694
+ QUnit.test("Recursive Hierarchy: delete & expandTo, one ancestor", async function (assert) {
28695
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
28696
+ const sView = `
28697
+ <t:Table id="table" rows="{path : '/EMPLOYEES',
28698
+ parameters : {
28699
+ $$aggregation : {
28700
+ expandTo : 4,
28701
+ hierarchyQualifier : 'OrgChart'
28702
+ }
28703
+ }}" threshold="0" visibleRowCount="4">
28704
+ <Text id="expanded" text="{= %{@$ui5.node.isExpanded} }"/>
28705
+ <Text text="{= %{@$ui5.node.level} }"/>
28706
+ <Text text="{ID}"/>
28707
+ <Text text="{MANAGER_ID}"/>
28708
+ <Text id="name" text="{Name}"/>
28709
+ </t:Table>`;
28209
28710
 
28210
- // code under test
28211
- oBeta.expand();
28711
+ // 0 Alpha
28712
+ // 1 Beta (deleted)
28713
+ // 2 Gamma (visible during the delete)
28714
+ // 3 Delta (visible during the delete)
28715
+ // 4 Epsilon (invisible during the delete)
28716
+ // 5 Zeta (only helps with the eventing)
28717
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
28718
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
28719
+ + ",NodeProperty='ID',Levels=4)"
28720
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
28721
+ + "&$count=true&$skip=0&$top=4", {
28722
+ "@odata.count" : "6",
28723
+ value : [{
28724
+ DescendantCount : "4",
28725
+ DistanceFromRoot : "0",
28726
+ DrillState : "expanded",
28727
+ ID : "0",
28728
+ MANAGER_ID : null,
28729
+ Name : "Alpha"
28730
+ }, {
28731
+ DescendantCount : "3",
28732
+ DistanceFromRoot : "1",
28733
+ DrillState : "expanded",
28734
+ ID : "1",
28735
+ MANAGER_ID : "0",
28736
+ Name : "Beta"
28737
+ }, {
28738
+ DescendantCount : "1",
28739
+ DistanceFromRoot : "2",
28740
+ DrillState : "expanded",
28741
+ ID : "2",
28742
+ MANAGER_ID : "1",
28743
+ Name : "Gamma"
28744
+ }, {
28745
+ DescendantCount : "0",
28746
+ DistanceFromRoot : "3",
28747
+ DrillState : "collapsed",
28748
+ ID : "3",
28749
+ MANAGER_ID : "2",
28750
+ Name : "Delta"
28751
+ }]
28752
+ })
28753
+ .expectChange("expanded", [true, true, true, false])
28754
+ .expectChange("name", ["Alpha", "Beta", "Gamma", "Delta"]);
28212
28755
 
28213
- await this.waitForChanges(assert, "expand again");
28214
- }
28756
+ await this.createView(assert, sView, oModel);
28215
28757
 
28216
- checkTable("finally", assert, oTable, [
28758
+ const oTable = this.oView.byId("table");
28759
+ checkTable("initially", assert, oTable, [
28217
28760
  "/EMPLOYEES('0')",
28218
28761
  "/EMPLOYEES('1')",
28219
28762
  "/EMPLOYEES('2')",
@@ -28221,161 +28764,655 @@ sap.ui.define([
28221
28764
  ], [
28222
28765
  [true, 1, "0", "", "Alpha"],
28223
28766
  [true, 2, "1", "0", "Beta"],
28224
- [false, 3, "2", "1", "Gamma"],
28225
- [false, 1, "3", "", "Delta"]
28226
- ], 4);
28767
+ [true, 3, "2", "1", "Gamma"],
28768
+ [false, 4, "3", "2", "Delta"]
28769
+ ], 6);
28770
+
28771
+ this.expectChange("expanded", [, false]) // Beta is collapsed before being deleted
28772
+ .expectRequest("DELETE EMPLOYEES('1')")
28773
+ .expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
28774
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
28775
+ + ",NodeProperty='ID',Levels=4)"
28776
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
28777
+ + "&$skip=1&$top=1", {
28778
+ value : [{
28779
+ DescendantCount : "0",
28780
+ DistanceFromRoot : "0",
28781
+ DrillState : "leaf",
28782
+ ID : "5",
28783
+ MANAGER_ID : null,
28784
+ Name : "Zeta"
28785
+ }]
28786
+ })
28787
+ .expectChange("expanded", [undefined]) // Alpha is now a leaf
28788
+ .expectChange("name", [, "Zeta"]);
28789
+
28790
+ await Promise.all([
28791
+ oTable.getRows()[1].getBindingContext().delete(), // code under test
28792
+ this.waitForChanges(assert, "delete Beta")
28793
+ ]);
28794
+
28795
+ checkTable("finally", assert, oTable, [
28796
+ "/EMPLOYEES('0')",
28797
+ "/EMPLOYEES('5')"
28798
+ ], [
28799
+ [undefined, 1, "0", "", "Alpha"], // now a leaf
28800
+ [undefined, 1, "5", "", "Zeta"]
28801
+ ]);
28227
28802
  });
28228
- });
28229
28803
 
28230
28804
  //*********************************************************************************************
28231
- // Scenario: Deferred delete in a recursive hierarchy. Before reinserting the node, delete two
28232
- // other nodes, so that both the parent's position and the deleted node's position within the
28233
- // level cache change.
28234
- // * Expand Beta
28235
- // * Deferred delete Delta
28236
- // * Delete Gamma (Beta becomes leaf) and Alpha
28237
- // * Reinsert Delta (Beta becomes expanded again)
28238
- // JIRA: CPOUI5ODATAV4-2224
28239
- QUnit.test("Recursive Hierarchy: delete and change reinsertion index", async function (assert) {
28805
+ // Scenario: Delete node Epsilon in a recursive hierarchy, preloaded via expandTo. The parent
28806
+ // node Gamma has not been loaded yet, but the grandparent Beta has. Load Gamma and Delta,
28807
+ // delete Delta, so that two ancestors need to be adjusted. In the end, collapse Beta to see
28808
+ // that it was adjusted correctly.
28809
+ // JIRA: CPOUI5ODATAV4-2302
28810
+ QUnit.test("Recursive Hierarchy: delete & expandTo, two ancestors", async function (assert) {
28240
28811
  const oModel = this.createTeaBusiModel({autoExpandSelect : true});
28241
28812
  const sView = `
28242
- <Table id="table" items="{path : '/EMPLOYEES',
28813
+ <t:Table id="table" rows="{path : '/EMPLOYEES',
28243
28814
  parameters : {
28244
28815
  $$aggregation : {
28816
+ expandTo : 3,
28245
28817
  hierarchyQualifier : 'OrgChart'
28246
28818
  }
28247
- }}">
28819
+ }}" threshold="0" visibleRowCount="2">
28248
28820
  <Text id="expanded" text="{= %{@$ui5.node.isExpanded} }"/>
28249
28821
  <Text text="{= %{@$ui5.node.level} }"/>
28250
28822
  <Text text="{ID}"/>
28251
28823
  <Text text="{MANAGER_ID}"/>
28252
28824
  <Text id="name" text="{Name}"/>
28253
- </Table>`;
28825
+ </t:Table>`;
28254
28826
 
28255
- // 0 Alpha (delete to change Beta's index)
28256
- // 1 Beta
28257
- // 2 Gamma (delete to change Delta's index in the level cache and make Beta a leaf)
28258
- // 3 Delta (deferred delete and reinsert)
28259
- // 4 Epsilon
28260
- this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels"
28261
- + "(HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart',NodeProperty='ID'"
28262
- + ",Levels=1)"
28263
- + "&$select=DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=100", {
28264
- "@odata.count" : "3",
28827
+ // 0 Alpha
28828
+ // 1 Beta (grandparent)
28829
+ // 2 Gamma (invisible during the 1st delete)
28830
+ // 3 Delta (invisible during the 1st delete, deleted later)
28831
+ // 4 Epsilon (deleted)
28832
+ // 5 Zeta
28833
+ // 6 Eta
28834
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
28835
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
28836
+ + ",NodeProperty='ID',Levels=3)"
28837
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
28838
+ + "&$count=true&$skip=0&$top=2", {
28839
+ "@odata.count" : "7",
28265
28840
  value : [{
28266
- DrillState : "collapsed",
28841
+ DescendantCount : "0",
28842
+ DistanceFromRoot : "0",
28843
+ DrillState : "leaf",
28267
28844
  ID : "0",
28268
28845
  MANAGER_ID : null,
28269
28846
  Name : "Alpha"
28270
28847
  }, {
28271
- DrillState : "collapsed",
28848
+ DescendantCount : "3",
28849
+ DistanceFromRoot : "0",
28850
+ DrillState : "expanded",
28272
28851
  ID : "1",
28273
28852
  MANAGER_ID : null,
28274
28853
  Name : "Beta"
28275
- }, {
28854
+ }]
28855
+ })
28856
+ .expectChange("expanded", [undefined, true])
28857
+ .expectChange("name", ["Alpha", "Beta"]);
28858
+
28859
+ await this.createView(assert, sView, oModel);
28860
+
28861
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
28862
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
28863
+ + ",NodeProperty='ID'" + ",Levels=3)"
28864
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
28865
+ + "&$skip=4&$top=2", {
28866
+ value : [{
28867
+ DescendantCount : "0",
28868
+ DistanceFromRoot : "2",
28276
28869
  DrillState : "collapsed",
28277
28870
  ID : "4",
28278
- MANAGER_ID : null,
28871
+ MANAGER_ID : "3",
28279
28872
  Name : "Epsilon"
28873
+ }, {
28874
+ DescendantCount : "1",
28875
+ DistanceFromRoot : "0",
28876
+ DrillState : "expanded",
28877
+ ID : "5",
28878
+ MANAGER_ID : null,
28879
+ Name : "Zeta"
28280
28880
  }]
28281
28881
  })
28282
- .expectChange("expanded", [false, false, false])
28283
- .expectChange("name", ["Alpha", "Beta", "Epsilon"]);
28882
+ .expectChange("expanded", [,,,, false, true])
28883
+ .expectChange("name", [,,,, "Epsilon", "Zeta"]);
28284
28884
 
28285
- await this.createView(assert, sView, oModel);
28885
+ const oTable = this.oView.byId("table");
28886
+ oTable.setFirstVisibleRow(4);
28286
28887
 
28287
- this.expectRequest("EMPLOYEES"
28288
- + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '1'),1)"
28289
- + "&$select=DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=100", {
28290
- "@odata.count" : "2",
28888
+ await this.waitForChanges(assert, "scroll down creating gap");
28889
+
28890
+ checkTable("before delete", assert, oTable, [
28891
+ "/EMPLOYEES('0')",
28892
+ "/EMPLOYEES('1')",
28893
+ "/EMPLOYEES('4')",
28894
+ "/EMPLOYEES('5')"
28895
+ ], [
28896
+ [false, 3, "4", "3", "Epsilon"],
28897
+ [true, 1, "5", "", "Zeta"]
28898
+ ], 7);
28899
+
28900
+ this.expectRequest("DELETE EMPLOYEES('4')")
28901
+ .expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
28902
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
28903
+ + ",NodeProperty='ID',Levels=3)"
28904
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
28905
+ + "&$skip=5&$top=1", {
28291
28906
  value : [{
28292
- DrillState : "collapsed",
28907
+ DescendantCount : "0",
28908
+ DistanceFromRoot : "1",
28909
+ DrillState : "leaf",
28910
+ ID : "6",
28911
+ MANAGER_ID : "5",
28912
+ Name : "Eta"
28913
+ }]
28914
+ })
28915
+ .expectChange("expanded", [,,,, true])
28916
+ .expectChange("name", [,,,, "Zeta", "Eta"]);
28917
+
28918
+ await Promise.all([
28919
+ // code under test
28920
+ oTable.getRows()[0].getBindingContext().delete(),
28921
+ this.waitForChanges(assert, "1st delete")
28922
+ ]);
28923
+
28924
+ checkTable("after 1st delete", assert, oTable, [
28925
+ "/EMPLOYEES('0')",
28926
+ "/EMPLOYEES('1')",
28927
+ "/EMPLOYEES('5')",
28928
+ "/EMPLOYEES('6')"
28929
+ ], [
28930
+ [true, 1, "5", "", "Zeta"],
28931
+ [undefined, 2, "6", "5", "Eta"]
28932
+ ], 6);
28933
+
28934
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
28935
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
28936
+ + ",NodeProperty='ID',Levels=3)"
28937
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
28938
+ + "&$skip=2&$top=2", {
28939
+ value : [
28940
+ {
28941
+ DescendantCount : "1",
28942
+ DistanceFromRoot : "1",
28943
+ DrillState : "expanded",
28944
+ ID : "2",
28945
+ MANAGER_ID : "1",
28946
+ Name : "Gamma"
28947
+ }, {
28948
+ DescendantCount : "0",
28949
+ DistanceFromRoot : "2",
28950
+ DrillState : "collapsed", // "leaf" is similar (nothing to do)
28951
+ ID : "3",
28952
+ MANAGER_ID : "2",
28953
+ Name : "Delta"
28954
+ }
28955
+ ]
28956
+ })
28957
+ .expectChange("expanded", [, , true, false])
28958
+ .expectChange("name", [, , "Gamma", "Delta"]);
28959
+
28960
+ oTable.setFirstVisibleRow(2);
28961
+
28962
+ await this.waitForChanges(assert, "scroll up closing gap");
28963
+
28964
+ checkTable("before 2nd delete", assert, oTable, [
28965
+ "/EMPLOYEES('0')",
28966
+ "/EMPLOYEES('1')",
28967
+ "/EMPLOYEES('2')",
28968
+ "/EMPLOYEES('3')",
28969
+ "/EMPLOYEES('5')",
28970
+ "/EMPLOYEES('6')"
28971
+ ], [
28972
+ [true, 2, "2", "1", "Gamma"],
28973
+ [false, 3, "3", "2", "Delta"]
28974
+ ]);
28975
+
28976
+ this.expectRequest("DELETE EMPLOYEES('3')")
28977
+ .expectChange("expanded", [,, undefined, true]) // Gamma becomes leaf
28978
+ .expectChange("name", [,,, "Zeta"]);
28979
+
28980
+ await Promise.all([
28981
+ oTable.getRows()[1].getBindingContext().delete(), // code under test
28982
+ this.waitForChanges(assert, "2nd delete")
28983
+ ]);
28984
+
28985
+ checkTable("after 2nd delete", assert, oTable, [
28986
+ "/EMPLOYEES('0')",
28987
+ "/EMPLOYEES('1')",
28988
+ "/EMPLOYEES('2')",
28989
+ "/EMPLOYEES('5')",
28990
+ "/EMPLOYEES('6')"
28991
+ ], [
28992
+ [undefined, 2, "2", "1", "Gamma"],
28993
+ [true, 1, "5", "", "Zeta"]
28994
+ ]);
28995
+
28996
+ this.expectChange("expanded", [, true, undefined])
28997
+ .expectChange("name", [, "Beta", "Gamma"]);
28998
+
28999
+ oTable.setFirstVisibleRow(1);
29000
+
29001
+ await this.waitForChanges(assert, "make Beta visible");
29002
+
29003
+ checkTable("after making Beta visible", assert, oTable, [
29004
+ "/EMPLOYEES('0')",
29005
+ "/EMPLOYEES('1')",
29006
+ "/EMPLOYEES('2')",
29007
+ "/EMPLOYEES('5')",
29008
+ "/EMPLOYEES('6')"
29009
+ ], [
29010
+ [true, 1, "1", "", "Beta"],
29011
+ [undefined, 2, "2", "1", "Gamma"]
29012
+ ]);
29013
+
29014
+ this.expectChange("expanded", [, false, true])
29015
+ .expectChange("name", [,, "Zeta"]);
29016
+
29017
+ oTable.getRows()[0].getBindingContext().collapse();
29018
+
29019
+ await this.waitForChanges(assert, "collapse Beta");
29020
+
29021
+ checkTable("after collapse", assert, oTable, [
29022
+ "/EMPLOYEES('0')",
29023
+ "/EMPLOYEES('1')",
29024
+ "/EMPLOYEES('5')",
29025
+ "/EMPLOYEES('6')"
29026
+ ], [
29027
+ [false, 1, "1", "", "Beta"],
29028
+ [true, 1, "5", "", "Zeta"]
29029
+ ]);
29030
+ });
29031
+
29032
+ //*********************************************************************************************
29033
+ // Scenario: Delete node Epsilon, preloaded via expandTo and expanded manually. Its parent Delta
29034
+ // is not loaded yet. Collapse Beta to see that it is not accidentally adjusted instead of
29035
+ // Delta. Collapse Alpha to see that it has been adjusted.
29036
+ // JIRA: CPOUI5ODATAV4-2302
29037
+ QUnit.test("Recursive Hierarchy: delete & expandTo, invisible parent", async function (assert) {
29038
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
29039
+ const sView = `
29040
+ <t:Table id="table" rows="{path : '/EMPLOYEES',
29041
+ parameters : {
29042
+ $$aggregation : {
29043
+ expandTo : 3,
29044
+ hierarchyQualifier : 'OrgChart'
29045
+ }
29046
+ }}" threshold="0" visibleRowCount="3">
29047
+ <Text id="expanded" text="{= %{@$ui5.node.isExpanded} }"/>
29048
+ <Text text="{= %{@$ui5.node.level} }"/>
29049
+ <Text text="{ID}"/>
29050
+ <Text text="{MANAGER_ID}"/>
29051
+ <Text id="name" text="{Name}"/>
29052
+ </t:Table>`;
29053
+
29054
+ // 0 Alpha
29055
+ // 1 Beta
29056
+ // 2 Gamma
29057
+ // 3 Delta (invisible parent)
29058
+ // 4 Epsilon (deleted)
29059
+ // 4.1 Omega
29060
+ // 5 Zeta
29061
+ // 6 Theta
29062
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
29063
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
29064
+ + ",NodeProperty='ID',Levels=3)"
29065
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
29066
+ + "&$count=true&$skip=0&$top=3", {
29067
+ "@odata.count" : "7",
29068
+ value : [{
29069
+ DescendantCount : "4",
29070
+ DistanceFromRoot : "0",
29071
+ DrillState : "expanded",
29072
+ ID : "0",
29073
+ MANAGER_ID : null,
29074
+ Name : "Alpha"
29075
+ }, {
29076
+ DescendantCount : "1",
29077
+ DistanceFromRoot : "1",
29078
+ DrillState : "expanded",
29079
+ ID : "1",
29080
+ MANAGER_ID : "0",
29081
+ Name : "Beta"
29082
+ }, {
29083
+ DescendantCount : "0",
29084
+ DistanceFromRoot : "2",
29085
+ DrillState : "leaf",
28293
29086
  ID : "2",
28294
29087
  MANAGER_ID : "1",
28295
29088
  Name : "Gamma"
29089
+ }]
29090
+ })
29091
+ .expectChange("expanded", [true, true, undefined])
29092
+ .expectChange("name", ["Alpha", "Beta", "Gamma"]);
29093
+
29094
+ await this.createView(assert, sView, oModel);
29095
+
29096
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
29097
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart',"
29098
+ + "NodeProperty='ID',Levels=3)"
29099
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
29100
+ + "&$skip=4&$top=3", {
29101
+ value : [{
29102
+ DescendantCount : "0",
29103
+ DistanceFromRoot : "2",
29104
+ DrillState : "collapsed",
29105
+ ID : "4",
29106
+ MANAGER_ID : "3",
29107
+ Name : "Epsilon"
29108
+ }, {
29109
+ DescendantCount : "0",
29110
+ DistanceFromRoot : "0",
29111
+ DrillState : "leaf",
29112
+ ID : "5",
29113
+ MANAGER_ID : null,
29114
+ Name : "Zeta"
28296
29115
  }, {
29116
+ DescendantCount : "0",
29117
+ DistanceFromRoot : "0",
28297
29118
  DrillState : "leaf",
28298
- ID : "3",
28299
- MANAGER_ID : "1",
28300
- Name : "Delta"
29119
+ ID : "6",
29120
+ MANAGER_ID : null,
29121
+ Name : "Theta"
28301
29122
  }]
28302
29123
  })
28303
- .expectChange("expanded", [, true,, undefined, false])
28304
- .expectChange("name", [,, "Gamma", "Delta", "Epsilon"]);
29124
+ .expectChange("expanded", [,,,, false])
29125
+ .expectChange("name", [,,,, "Epsilon", "Zeta", "Theta"]);
28305
29126
 
28306
29127
  const oTable = this.oView.byId("table");
28307
- oTable.getItems()[1].getBindingContext().expand();
29128
+ oTable.setFirstVisibleRow(4);
28308
29129
 
28309
- await this.waitForChanges(assert, "expand Beta");
29130
+ await this.waitForChanges(assert, "scroll down creating gap");
28310
29131
 
28311
- checkTable("before delete", assert, oTable, [
29132
+ this.expectRequest("EMPLOYEES?$apply=descendants($root/EMPLOYEES,OrgChart,ID"
29133
+ + ",filter(ID eq '4'),1)&$select=DrillState,ID,MANAGER_ID,Name&$count=true"
29134
+ + "&$skip=0&$top=3", {
29135
+ "@odata.count" : "1",
29136
+ value : [{
29137
+ DrillState : "leaf",
29138
+ ID : "4.1",
29139
+ MANAGER_ID : "4",
29140
+ Name : "Omega"
29141
+ }]
29142
+ })
29143
+ .expectChange("expanded", [,,,, true])
29144
+ .expectChange("name", [,,,,, "Omega", "Zeta"]);
29145
+
29146
+ await Promise.all([
29147
+ oTable.getRows()[0].getBindingContext().expand(),
29148
+ this.waitForChanges(assert, "expand Epsilon")
29149
+ ]);
29150
+
29151
+ checkTable("after expanding Epsilon", assert, oTable, [
29152
+ "/EMPLOYEES('0')",
29153
+ "/EMPLOYEES('1')",
29154
+ "/EMPLOYEES('2')",
29155
+ "/EMPLOYEES('4')",
29156
+ "/EMPLOYEES('4.1')",
29157
+ "/EMPLOYEES('5')",
29158
+ "/EMPLOYEES('6')"
29159
+ ], [
29160
+ [true, 3, "4", "3", "Epsilon"],
29161
+ [undefined, 4, "4.1", "4", "Omega"],
29162
+ [undefined, 1, "5", "", "Zeta"]
29163
+ ], 8);
29164
+
29165
+ this.expectRequest("DELETE EMPLOYEES('4')")
29166
+ // Note: the table sets the first visible row to 3 due to the length
29167
+ .expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
29168
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
29169
+ + ",NodeProperty='ID',Levels=3)"
29170
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
29171
+ + "&$skip=3&$top=1", {
29172
+ value : [{
29173
+ DescendantCount : "0",
29174
+ DistanceFromRoot : "1",
29175
+ DrillState : "leaf",
29176
+ ID : "3",
29177
+ MANAGER_ID : "0",
29178
+ Name : "Delta"
29179
+ }]
29180
+ })
29181
+ .expectChange("expanded", [,,,, false]) // Epsilon is collapsed before the delete
29182
+ .expectChange("name", [,,, "Delta", "Zeta", "Theta"]);
29183
+
29184
+ await Promise.all([
29185
+ oTable.getRows()[0].getBindingContext().delete(),
29186
+ this.waitForChanges(assert, "delete")
29187
+ ]);
29188
+
29189
+ checkTable("after delete", assert, oTable, [
28312
29190
  "/EMPLOYEES('0')",
28313
29191
  "/EMPLOYEES('1')",
28314
29192
  "/EMPLOYEES('2')",
28315
29193
  "/EMPLOYEES('3')",
28316
- "/EMPLOYEES('4')"
29194
+ "/EMPLOYEES('5')",
29195
+ "/EMPLOYEES('6')"
28317
29196
  ], [
28318
- [false, 1, "0", "", "Alpha"],
28319
- [true, 1, "1", "", "Beta"],
28320
- [false, 2, "2", "1", "Gamma"],
28321
- [undefined, 2, "3", "1", "Delta"],
28322
- [false, 1, "4", "", "Epsilon"]
28323
- ], 5);
29197
+ [undefined, "2", "3", "0", "Delta"],
29198
+ [undefined, "1", "5", "", "Zeta"],
29199
+ [undefined, "1", "6", "", "Theta"]
29200
+ ]);
28324
29201
 
28325
- this.expectChange("expanded", [,,, false])
28326
- .expectChange("name", [,,, "Epsilon"]);
29202
+ this.expectChange("expanded", [true, true])
29203
+ .expectChange("name", ["Alpha", "Beta", "Gamma"]);
28327
29204
 
28328
- // code under test
28329
- const oDelta = oTable.getItems()[3].getBindingContext();
28330
- const oDeleteDeltaPromise = oDelta.delete("doNotSubmit");
29205
+ oTable.setFirstVisibleRow(0);
28331
29206
 
28332
- await this.waitForChanges(assert, "delete Delta");
29207
+ await this.waitForChanges(assert, "make Alpha & Beta visible");
28333
29208
 
28334
- this.expectChange("expanded", [undefined, false])
28335
- .expectChange("name", ["Beta", "Epsilon"])
28336
- .expectRequest("DELETE EMPLOYEES('2')")
28337
- .expectRequest("DELETE EMPLOYEES('0')");
29209
+ this.expectChange("expanded", [, false])
29210
+ .expectChange("name", [,, "Delta"]);
28338
29211
 
28339
- // code under test
28340
- const oDeleteGammaPromise = oTable.getItems()[2].getBindingContext().delete();
28341
- const oDeleteAlphaPromise = oTable.getItems()[0].getBindingContext().delete();
29212
+ oTable.getRows()[1].getBindingContext().collapse();
28342
29213
 
28343
- await Promise.all([
28344
- oDeleteGammaPromise,
28345
- oDeleteAlphaPromise,
28346
- this.waitForChanges(assert, "delete Gamma and Alpha")
29214
+ await this.waitForChanges(assert, "collapse Beta");
29215
+
29216
+ checkTable("after collapsing Beta", assert, oTable, [
29217
+ "/EMPLOYEES('0')",
29218
+ "/EMPLOYEES('1')",
29219
+ "/EMPLOYEES('3')",
29220
+ "/EMPLOYEES('5')",
29221
+ "/EMPLOYEES('6')"
29222
+ ], [
29223
+ [true, 1, "0", "", "Alpha"],
29224
+ [false, 2, "1", "0", "Beta"],
29225
+ [undefined, 2, "3", "0", "Delta"]
28347
29226
  ]);
28348
29227
 
28349
- checkTable("after delete", assert, oTable, [
29228
+ this.expectChange("expanded", [false, undefined])
29229
+ .expectChange("name", [, "Zeta", "Theta"]);
29230
+
29231
+ oTable.getRows()[0].getBindingContext().collapse();
29232
+
29233
+ await this.waitForChanges(assert, "collapse Alpha");
29234
+
29235
+ checkTable("after collapsing Alpha", assert, oTable, [
29236
+ "/EMPLOYEES('0')",
29237
+ "/EMPLOYEES('5')",
29238
+ "/EMPLOYEES('6')"
29239
+ ], [
29240
+ [false, 1, "0", "", "Alpha"],
29241
+ [undefined, 1, "5", "", "Zeta"],
29242
+ [undefined, 1, "6", "", "Theta"]
29243
+ ]);
29244
+ });
29245
+
29246
+ //*********************************************************************************************
29247
+ // Scenario: Delete node Beta, preloaded via expandTo. Its parent is not loaded yet, hence no
29248
+ // ancestor can be found at all. Before the deletion collapse Gamma manually. See that after the
29249
+ // deletion Epsilon is requested correctly when Gamma is expanded again.
29250
+ // JIRA: CPOUI5ODATAV4-2302
29251
+ QUnit.test("Recursive Hierarchy: delete & expandTo, parent missing", async function (assert) {
29252
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
29253
+ const sView = `
29254
+ <t:Table firstVisibleRow="1" id="table" rows="{path : '/EMPLOYEES',
29255
+ parameters : {
29256
+ $$aggregation : {
29257
+ expandTo : 3,
29258
+ hierarchyQualifier : 'OrgChart'
29259
+ }
29260
+ }}" threshold="0" visibleRowCount="3">
29261
+ <Text id="expanded" text="{= %{@$ui5.node.isExpanded} }"/>
29262
+ <Text text="{= %{@$ui5.node.level} }"/>
29263
+ <Text text="{ID}"/>
29264
+ <Text text="{MANAGER_ID}"/>
29265
+ <Text id="name" text="{Name}"/>
29266
+ </t:Table>`;
29267
+
29268
+ // 0 Alpha (invisible parent)
29269
+ // 1 Beta (delete)
29270
+ // 2 Gamma (manually collapsed before delete)
29271
+ // 3 Delta (loaded before the delete)
29272
+ // 4 Epsilon (loaded when re-expanding after the delete)
29273
+ // 5 Zeta
29274
+ // 6 Eta
29275
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
29276
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
29277
+ + ",NodeProperty='ID',Levels=3)"
29278
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
29279
+ + "&$count=true&$skip=1&$top=3", {
29280
+ "@odata.count" : "7",
29281
+ value : [{
29282
+ DescendantCount : "0",
29283
+ DistanceFromRoot : "1",
29284
+ DrillState : "leaf",
29285
+ ID : "1",
29286
+ MANAGER_ID : "0",
29287
+ Name : "Beta"
29288
+ }, {
29289
+ DescendantCount : "2",
29290
+ DistanceFromRoot : "1",
29291
+ DrillState : "expanded",
29292
+ ID : "2",
29293
+ MANAGER_ID : "0",
29294
+ Name : "Gamma"
29295
+ }, {
29296
+ DescendantCount : "0",
29297
+ DistanceFromRoot : "2",
29298
+ DrillState : "leaf",
29299
+ ID : "3",
29300
+ MANAGER_ID : "2",
29301
+ Name : "Delta"
29302
+ }]
29303
+ })
29304
+ .expectChange("expanded", [, undefined, true, undefined])
29305
+ .expectChange("name", [, "Beta", "Gamma", "Delta"]);
29306
+
29307
+ await this.createView(assert, sView, oModel);
29308
+
29309
+ const oTable = this.oView.byId("table");
29310
+ checkTable("initial", assert, oTable, [
28350
29311
  "/EMPLOYEES('1')",
28351
- "/EMPLOYEES('4')"
29312
+ "/EMPLOYEES('2')",
29313
+ "/EMPLOYEES('3')"
28352
29314
  ], [
28353
- [undefined, 1, "1", "", "Beta"],
28354
- [false, 1, "4", "", "Epsilon"]
28355
- ], 2);
29315
+ [undefined, 2, "1", "0", "Beta"],
29316
+ [true, 2, "2", "0", "Gamma"],
29317
+ [undefined, 3, "3", "2", "Delta"]
29318
+ ], 7);
29319
+
29320
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
29321
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
29322
+ + ",NodeProperty='ID',Levels=3)"
29323
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
29324
+ + "&$skip=5&$top=1", {
29325
+ value : [{
29326
+ DescendantCount : "0",
29327
+ DistanceFromRoot : "1",
29328
+ DrillState : "leaf",
29329
+ ID : "5",
29330
+ MANAGER_ID : "0",
29331
+ Name : "Zeta"
29332
+ }]
29333
+ })
29334
+ .expectChange("expanded", [,, false])
29335
+ .expectChange("name", [,,, "Zeta"]);
28356
29336
 
28357
- this.expectCanceledError("Failed to delete /EMPLOYEES('3')",
28358
- "Request canceled: DELETE EMPLOYEES('3'); group: doNotSubmit")
28359
- .expectChange("expanded", [true, undefined, false])
28360
- .expectChange("name", [, "Delta", "Epsilon"]);
29337
+ oTable.getRows()[1].getBindingContext().collapse();
28361
29338
 
28362
- // code under test
28363
- oDelta.resetChanges();
29339
+ await this.waitForChanges(assert, "collapse Gamma");
29340
+
29341
+ checkTable("after collapsing Gamma", assert, oTable, [
29342
+ "/EMPLOYEES('1')",
29343
+ "/EMPLOYEES('2')",
29344
+ "/EMPLOYEES('5')"
29345
+ ], [
29346
+ [undefined, 2, "1", "0", "Beta"],
29347
+ [false, 2, "2", "0", "Gamma"],
29348
+ [undefined, 2, "5", "0", "Zeta"]
29349
+ ], 5);
29350
+
29351
+ this.expectRequest("DELETE EMPLOYEES('1')")
29352
+ .expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
29353
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
29354
+ + ",NodeProperty='ID',Levels=3)"
29355
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
29356
+ + "&$skip=5&$top=1", {
29357
+ value : [{
29358
+ DescendantCount : "0",
29359
+ DistanceFromRoot : "1",
29360
+ DrillState : "leaf",
29361
+ ID : "6",
29362
+ MANAGER_ID : "0",
29363
+ Name : "Eta"
29364
+ }]
29365
+ })
29366
+ .expectChange("expanded", [, false, undefined])
29367
+ .expectChange("name", [, "Gamma", "Zeta", "Eta"]);
28364
29368
 
28365
29369
  await Promise.all([
28366
- checkCanceled(assert, oDeleteDeltaPromise),
28367
- this.waitForChanges(assert, "reinsert delta")
29370
+ oTable.getRows()[0].getBindingContext().delete(),
29371
+ this.waitForChanges(assert, "delete Beta")
28368
29372
  ]);
28369
29373
 
28370
- checkTable("after reinsert", assert, oTable, [
28371
- "/EMPLOYEES('1')",
29374
+ checkTable("after delete Beta", assert, oTable, [
29375
+ "/EMPLOYEES('2')",
29376
+ "/EMPLOYEES('5')",
29377
+ "/EMPLOYEES('6')"
29378
+ ], [
29379
+ [false, 2, "2", "0", "Gamma"],
29380
+ [undefined, 2, "5", "0", "Zeta"],
29381
+ [undefined, 2, "6", "0", "Eta"]
29382
+ ], 4);
29383
+
29384
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
29385
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
29386
+ + ",NodeProperty='ID',Levels=3)"
29387
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name"
29388
+ + "&$skip=3&$top=1", {
29389
+ value : [{
29390
+ DescendantCount : "0",
29391
+ DistanceFromRoot : "2",
29392
+ DrillState : "leaf",
29393
+ ID : "4",
29394
+ MANAGER_ID : "2",
29395
+ Name : "Epsilon"
29396
+ }]
29397
+ })
29398
+ .expectChange("expanded", [, true])
29399
+ .expectChange("name", [,, "Delta", "Epsilon"]);
29400
+
29401
+ oTable.getRows()[0].getBindingContext().expand();
29402
+
29403
+ await this.waitForChanges(assert, "expand Gamma");
29404
+
29405
+ checkTable("after expand Gamma", assert, oTable, [
29406
+ "/EMPLOYEES('2')",
28372
29407
  "/EMPLOYEES('3')",
28373
- "/EMPLOYEES('4')"
29408
+ "/EMPLOYEES('4')",
29409
+ "/EMPLOYEES('5')",
29410
+ "/EMPLOYEES('6')"
28374
29411
  ], [
28375
- [true, 1, "1", "", "Beta"],
28376
- [undefined, 2, "3", "1", "Delta"],
28377
- [false, 1, "4", "", "Epsilon"]
28378
- ], 3);
29412
+ [true, 2, "2", "0", "Gamma"],
29413
+ [undefined, 3, "3", "2", "Delta"],
29414
+ [undefined, 3, "4", "2", "Epsilon"]
29415
+ ], 6);
28379
29416
  });
28380
29417
 
28381
29418
  //*********************************************************************************************
@@ -28394,8 +29431,15 @@ sap.ui.define([
28394
29431
  // Move "Beta" so that "Gamma" becomes its parent (no change to context's index, but a persisted
28395
29432
  // node (again) becomes "created persisted"). Observe property change events for "@odata.etag".
28396
29433
  // JIRA: CPOUI5ODATAV4-2226
28397
- QUnit.test("Recursive Hierarchy: create new children", function (assert) {
28398
- var oBeta, oBetaCreated, oGamma, oGammaCreated, oListBinding, fnRespond, oRoot, oTable;
29434
+ //
29435
+ // Create a new root via "@$ui5.node.parent" : null (JIRA: CPOUI5ODATAV4-2355)
29436
+ //
29437
+ // "Refresh single" for stale elements; keep same context instance for created nodes throughout
29438
+ // collapse and side effects.
29439
+ // JIRA: CPOUI5ODATAV4-2374
29440
+ QUnit.test("Recursive Hierarchy: create new children, move 'em", function (assert) {
29441
+ var oBeta, oBetaCreated, oGamma, oGammaCreated, oListBinding, oNewRoot, fnRespond, oRoot,
29442
+ oTable;
28399
29443
 
28400
29444
  const oModel = this.createSpecialCasesModel({autoExpandSelect : true});
28401
29445
  const sFriend = "/Artists(ArtistID='99',IsActiveEntity=false)/_Friend";
@@ -28450,11 +29494,6 @@ sap.ui.define([
28450
29494
  ]);
28451
29495
  assert.strictEqual(oRoot.getIndex(), 0);
28452
29496
 
28453
- assert.throws(function () {
28454
- // code under test (missing "@$ui5.node.parent")
28455
- oListBinding.create({}, /*bSkipRefresh*/true);
28456
- }); // TypeError: Cannot read properties of undefined (reading 'getCanonicalPath')
28457
-
28458
29497
  // code under test (JIRA: CPOUI5ODATAV4-2272)
28459
29498
  const oLostChild = oListBinding.create({
28460
29499
  "@$ui5.node.parent" : oRoot,
@@ -28712,6 +29751,8 @@ sap.ui.define([
28712
29751
  ["", "", "", "", ""],
28713
29752
  ["", "", "", "", ""]
28714
29753
  ]);
29754
+ assert.strictEqual(oBeta.getModel(), oModel, "not destroyed by collapse");
29755
+ assert.strictEqual(oGamma.getModel(), oModel, "not destroyed by collapse");
28715
29756
 
28716
29757
  that.expectRequest(sFriend.slice(1) + "?$select=ArtistID,IsActiveEntity,Name,_/NodeID"
28717
29758
  + "&$filter=ArtistID eq '0' and IsActiveEntity eq false", {
@@ -28726,38 +29767,28 @@ sap.ui.define([
28726
29767
  .expectChange("etag", ["etag0.1"])
28727
29768
  .expectChange("name", ["Alpha #1"]);
28728
29769
 
28729
- oBeta = oGamma = null; // Note: side effect eventually destroys these!
28730
-
28731
29770
  return Promise.all([
28732
29771
  // code under test
28733
29772
  oListBinding.getHeaderContext().requestSideEffects(["Name"]),
28734
29773
  that.waitForChanges(assert, "side effect: Name for all rows")
28735
29774
  ]);
28736
29775
  }).then(function () {
28737
- that.expectRequest(sFriend.slice(1) + "?$apply=descendants($root" + sFriend
28738
- + ",OrgChart,_/NodeID,filter(ArtistID eq '0' and IsActiveEntity eq false),1)"
28739
- + "&$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID"
28740
- + "&$skip=0&$top=2", {
28741
- value : [{ //TODO Gamma might not be $skip=0!
29776
+ that.expectRequest(sFriend.slice(1) + "(ArtistID='2',IsActiveEntity=false)"
29777
+ + "?$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID", {
28742
29778
  "@odata.etag" : "etag2.3", // updated
28743
29779
  ArtistID : "2",
28744
29780
  IsActiveEntity : false,
28745
29781
  Name : "Gamma #1", // "side effect"
28746
- _ : {
28747
- DrillState : "leaf",
28748
- NodeID : "2,false"
28749
- }
28750
- }, {
29782
+ _ : null // not available w/ RAP for a non-hierarchical request
29783
+ })
29784
+ .expectRequest(sFriend.slice(1) + "(ArtistID='1',IsActiveEntity=false)"
29785
+ + "?$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID", {
28751
29786
  "@odata.etag" : "etag1.3", // updated
28752
29787
  ArtistID : "1",
28753
29788
  IsActiveEntity : false,
28754
29789
  Name : "Beta #1", // "side effect"
28755
- _ : {
28756
- DrillState : "leaf",
28757
- NodeID : "1,false"
28758
- }
28759
- }]
28760
- })
29790
+ _ : null // not available w/ RAP for a non-hierarchical request
29791
+ })
28761
29792
  .expectChange("etag", [, "etag2.3", "etag1.3"])
28762
29793
  .expectChange("name", [, "Gamma #1", "Beta #1"]);
28763
29794
 
@@ -28772,39 +29803,39 @@ sap.ui.define([
28772
29803
  sFriend + "(ArtistID='1',IsActiveEntity=false)"
28773
29804
  ], [
28774
29805
  [undefined, true, 1, "etag0.1", "Alpha #1"],
28775
- [undefined, undefined, 2, "etag2.3", "Gamma #1"],
28776
- [undefined, undefined, 2, "etag1.3", "Beta #1"]
29806
+ [false, undefined, 2, "etag2.3", "Gamma #1"],
29807
+ [false, undefined, 2, "etag1.3", "Beta #1"]
28777
29808
  ]);
28778
- [, oGamma, oBeta] = oListBinding.getCurrentContexts();
29809
+ const aCurrentContexts = oListBinding.getCurrentContexts();
29810
+ assert.strictEqual(oRoot, aCurrentContexts[0]);
29811
+ assert.strictEqual(oGamma, aCurrentContexts[1]);
29812
+ assert.strictEqual(oBeta, aCurrentContexts[2]);
28779
29813
 
28780
29814
  assert.strictEqual(oGamma.getIndex(), 1);
28781
29815
  assert.deepEqual(oGamma.getObject(), {
29816
+ "@$ui5.context.isTransient" : false,
28782
29817
  "@$ui5.node.level" : 2,
28783
29818
  "@odata.etag" : "etag2.3",
28784
29819
  ArtistID : "2",
28785
29820
  IsActiveEntity : false,
28786
29821
  Name : "Gamma #1",
28787
- _ : {
28788
- NodeID : "2,false"
28789
- }
29822
+ _ : null // Note: NodeID still unknown
28790
29823
  });
28791
- assert.strictEqual(oGamma.isTransient(), undefined, "persisted");
28792
- assert.strictEqual(oGamma.created(), undefined);
29824
+ assert.strictEqual(oGamma.isTransient(), false, "created persisted");
29825
+ assert.strictEqual(oGamma.created(), oGammaCreated, "unchanged");
28793
29826
 
28794
29827
  assert.strictEqual(oBeta.getIndex(), 2);
28795
29828
  assert.deepEqual(oBeta.getObject(), {
28796
- // "@$ui5.context.isTransient" deleted by #requestSideEffects/#expand
29829
+ "@$ui5.context.isTransient" : false,
28797
29830
  "@$ui5.node.level" : 2,
28798
29831
  "@odata.etag" : "etag1.3",
28799
29832
  ArtistID : "1",
28800
29833
  IsActiveEntity : false,
28801
29834
  Name : "Beta #1",
28802
- _ : {
28803
- NodeID : "1,false"
28804
- }
29835
+ _ : null // Note: NodeID still unknown
28805
29836
  });
28806
- assert.strictEqual(oBeta.isTransient(), undefined, "persisted");
28807
- assert.strictEqual(oBeta.created(), undefined);
29837
+ assert.strictEqual(oBeta.isTransient(), false, "created persisted");
29838
+ assert.strictEqual(oBeta.created(), oBetaCreated, "unchanged");
28808
29839
 
28809
29840
  return Promise.all([
28810
29841
  // code under test
@@ -28837,7 +29868,7 @@ sap.ui.define([
28837
29868
  sFriend + "(ArtistID='1',IsActiveEntity=false)"
28838
29869
  ], [
28839
29870
  [undefined, true, 1, "etag0.1", "Alpha #1"],
28840
- [undefined, true, 2, "etag2.3", "Gamma #1"],
29871
+ [false, true, 2, "etag2.3", "Gamma #1"],
28841
29872
  [false, undefined, 3, "etag1.4", "Beta #1"]
28842
29873
  ]);
28843
29874
  const aCurrentContexts = oListBinding.getCurrentContexts();
@@ -28847,46 +29878,171 @@ sap.ui.define([
28847
29878
 
28848
29879
  assert.strictEqual(oGamma.getIndex(), 1);
28849
29880
  assert.deepEqual(oGamma.getObject(), {
29881
+ "@$ui5.context.isTransient" : false,
28850
29882
  "@$ui5.node.isExpanded" : true,
28851
29883
  "@$ui5.node.level" : 2,
28852
29884
  "@odata.etag" : "etag2.3",
28853
29885
  ArtistID : "2",
28854
29886
  IsActiveEntity : false,
28855
29887
  Name : "Gamma #1",
28856
- _ : {
28857
- NodeID : "2,false"
28858
- }
29888
+ _ : null // Note: NodeID still unknown
28859
29889
  });
28860
- assert.strictEqual(oGamma.isTransient(), undefined, "persisted");
28861
- assert.strictEqual(oGamma.created(), undefined);
29890
+ assert.strictEqual(oGamma.isTransient(), false, "created persisted");
29891
+ assert.strictEqual(oGamma.created(), oGammaCreated, "unchanged");
28862
29892
 
28863
29893
  assert.strictEqual(oBeta.getIndex(), 2); // unchanged by #move
28864
29894
  assert.deepEqual(oBeta.getObject(), {
28865
- "@$ui5.context.isTransient" : false, // "moved"
29895
+ "@$ui5.context.isTransient" : false,
28866
29896
  "@$ui5.node.level" : 3,
28867
29897
  "@odata.etag" : "etag1.4",
28868
29898
  ArtistID : "1",
28869
29899
  IsActiveEntity : false,
28870
29900
  Name : "Beta #1",
28871
- _ : {
28872
- NodeID : "1,false"
28873
- }
29901
+ _ : null // Note: NodeID still unknown
28874
29902
  });
28875
29903
  assert.strictEqual(oBeta.isTransient(), false, "created persisted");
28876
- assert.ok(oBeta.created() instanceof Promise);
29904
+ assert.strictEqual(oBeta.created(), oBetaCreated, "unchanged");
28877
29905
 
28878
29906
  return oBeta.created(); // to prove that it's not rejected
29907
+ }).then(function () {
29908
+ that.expectChange("etag", [undefined, "etag0.1", "etag2.3"])
29909
+ .expectChange("name", ["Aleph", "Alpha #1", "Gamma #1"])
29910
+ .expectRequest({
29911
+ method : "POST",
29912
+ url : sFriend.slice(1),
29913
+ payload : {
29914
+ // not needed: "BestFriend@odata.bind" : null,
29915
+ Name : "Aleph"
29916
+ }
29917
+ }, {
29918
+ "@odata.etag" : "etag9.0",
29919
+ ArtistID : "9",
29920
+ IsActiveEntity : false,
29921
+ Name : "Aleph: ℵ" // side effect
29922
+ })
29923
+ .expectChange("etag", ["etag9.0"])
29924
+ .expectChange("name", ["Aleph: ℵ"]);
29925
+
29926
+ // code under test (JIRA: CPOUI5ODATAV4-2355)
29927
+ oNewRoot = oListBinding.create({
29928
+ "@$ui5.node.parent" : null,
29929
+ Name : "Aleph"
29930
+ }, /*bSkipRefresh*/true);
29931
+
29932
+ assert.strictEqual(oNewRoot.getIndex(), 0);
29933
+
29934
+ return Promise.all([
29935
+ oNewRoot.created(),
29936
+ that.waitForChanges(assert, "create new root")
29937
+ ]);
29938
+ }).then(function () {
29939
+ checkTable("after create new root", assert, oTable, [
29940
+ sFriend + "(ArtistID='9',IsActiveEntity=false)",
29941
+ sFriend + "(ArtistID='0',IsActiveEntity=false)",
29942
+ sFriend + "(ArtistID='2',IsActiveEntity=false)",
29943
+ sFriend + "(ArtistID='1',IsActiveEntity=false)"
29944
+ ], [
29945
+ [false, undefined, 1, "etag9.0", "Aleph: ℵ"],
29946
+ [undefined, true, 1, "etag0.1", "Alpha #1"],
29947
+ [false, true, 2, "etag2.3", "Gamma #1"]
29948
+ ]);
29949
+ assert.strictEqual(oNewRoot.isTransient(), false, "created persisted");
29950
+
29951
+ that.expectRequest(sFriend.slice(1) + "?$select=ArtistID,IsActiveEntity,Name,_/NodeID"
29952
+ + "&$filter=ArtistID eq '9' and IsActiveEntity eq false"
29953
+ + " or ArtistID eq '0' and IsActiveEntity eq false"
29954
+ + " or ArtistID eq '2' and IsActiveEntity eq false"
29955
+ + " or ArtistID eq '1' and IsActiveEntity eq false"
29956
+ + "&$top=4", {
29957
+ value : [{
29958
+ "@odata.etag" : "etag9.1",
29959
+ ArtistID : "9",
29960
+ IsActiveEntity : false,
29961
+ Name : "Aleph #2",
29962
+ _ : null // not available w/ RAP for a non-hierarchical request
29963
+ }, {
29964
+ "@odata.etag" : "etag0.2",
29965
+ ArtistID : "0",
29966
+ IsActiveEntity : false,
29967
+ Name : "Alpha #2",
29968
+ _ : null // not available w/ RAP for a non-hierarchical request
29969
+ }, {
29970
+ "@odata.etag" : "etag2.4",
29971
+ ArtistID : "2",
29972
+ IsActiveEntity : false,
29973
+ Name : "Gamma #2",
29974
+ _ : null // not available w/ RAP for a non-hierarchical request
29975
+ }, {
29976
+ "@odata.etag" : "etag1.5",
29977
+ ArtistID : "1",
29978
+ IsActiveEntity : false,
29979
+ Name : "Beta #2",
29980
+ _ : null // not available w/ RAP for a non-hierarchical request
29981
+ }]
29982
+ })
29983
+ .expectChange("etag", ["etag9.1", "etag0.2", "etag2.4"])
29984
+ .expectChange("name", ["Aleph #2", "Alpha #2", "Gamma #2"]);
29985
+
29986
+ return Promise.all([
29987
+ // code under test
29988
+ oListBinding.getHeaderContext().requestSideEffects(["Name"]),
29989
+ that.waitForChanges(assert, "side effect again: Name for all rows")
29990
+ ]);
29991
+ }).then(function () {
29992
+ checkTable("after side effect again: Name for all rows", assert, oTable, [
29993
+ sFriend + "(ArtistID='9',IsActiveEntity=false)",
29994
+ sFriend + "(ArtistID='0',IsActiveEntity=false)",
29995
+ sFriend + "(ArtistID='2',IsActiveEntity=false)",
29996
+ sFriend + "(ArtistID='1',IsActiveEntity=false)"
29997
+ ], [
29998
+ [false, undefined, 1, "etag9.1", "Aleph #2"],
29999
+ [undefined, true, 1, "etag0.2", "Alpha #2"],
30000
+ [false, true, 2, "etag2.4", "Gamma #2"]
30001
+ ]);
30002
+ assert.strictEqual(oBeta, oListBinding.getAllCurrentContexts()[3], "same instance");
30003
+
30004
+ that.expectChange("etag", [, "etag0.2", "etag2.4", "etag1.5"])
30005
+ .expectChange("name", [, "Alpha #2", "Gamma #2", "Beta #2"]);
30006
+
30007
+ oTable.setFirstVisibleRow(1);
30008
+
30009
+ return that.waitForChanges(assert, "scroll down to Beta");
30010
+ }).then(function () {
30011
+ checkTable("after scroll down to Beta", assert, oTable, [
30012
+ sFriend + "(ArtistID='9',IsActiveEntity=false)",
30013
+ sFriend + "(ArtistID='0',IsActiveEntity=false)",
30014
+ sFriend + "(ArtistID='2',IsActiveEntity=false)",
30015
+ sFriend + "(ArtistID='1',IsActiveEntity=false)"
30016
+ ], [
30017
+ [undefined, true, 1, "etag0.2", "Alpha #2"],
30018
+ [false, true, 2, "etag2.4", "Gamma #2"],
30019
+ [false, undefined, 3, "etag1.5", "Beta #2"]
30020
+ ]);
30021
+ assert.strictEqual(oBeta, oListBinding.getCurrentContexts()[2], "same instance");
30022
+ assert.strictEqual(oBeta.isTransient(), false, "created persisted");
30023
+ assert.strictEqual(oBeta.created(), oBetaCreated, "unchanged");
28879
30024
  });
28880
30025
  });
28881
30026
 
28882
30027
  //*********************************************************************************************
28883
- // Scenario: Show the first level of a recursive hierarchy ("Alpha", "Omega"), expand "Alpha"
28884
- // and "Beta" and collapse "Beta" again. Move "Alpha" so that "Omega" becomes its parent. Check
28885
- // that its children are moved as well. Expand "Beta" again and check the level of its children.
28886
- // "Alpha" is either moved as a node with children or first collapsed and later expanded.
30028
+ // Scenario: Show the first level of a recursive hierarchy ("Alpha", "Omega"), expand "Alpha".
30029
+ // Maybe expand "Beta" and collapse it again. Move "Alpha" so that "Omega" becomes its parent,
30030
+ // either as an expanded node with children or by first collapsing and later expanding. Check
30031
+ // that its children are moved as well.
28887
30032
  // JIRA: CPOUI5ODATAV4-2325
30033
+ //
30034
+ // Move "Kappa" so that "Beta" becomes its parent, thus expanding it again, then check the
30035
+ // level of the latter's children.
30036
+ // JIRA: CPOUI5ODATAV4-2326
30037
+ //
30038
+ // A failed move must not leave the node collapsed (JIRA: CPOUI5ODATAV4-2343)
30039
+ //
30040
+ // Determine the parent nodes of "Alpha", "Beta", "Kappa", and "Omega".
30041
+ // JIRA: CPOUI5ODATAV4-2323
28888
30042
  [false, true].forEach((bMoveCollapsed) => {
28889
- const sTitle = `Recursive Hierarchy: move node w/ children, collapsed=${bMoveCollapsed}`;
30043
+ [false, true].forEach((bExpandCollapseBeta) => {
30044
+ const sTitle = `Recursive Hierarchy: move node w/ children, collapsed=${bMoveCollapsed},
30045
+ "Beta" expanded/collapsed before=${bExpandCollapseBeta}`;
28890
30046
 
28891
30047
  QUnit.test(sTitle, async function (assert) {
28892
30048
  const oModel = this.createTeaBusiModel({autoExpandSelect : true});
@@ -28894,7 +30050,7 @@ sap.ui.define([
28894
30050
  <t:Table id="table" rows="{path : '/EMPLOYEES',
28895
30051
  parameters : {
28896
30052
  $$aggregation : {hierarchyQualifier : 'OrgChart'}
28897
- }}" threshold="0" visibleRowCount="5">
30053
+ }}" threshold="0" visibleRowCount="7">
28898
30054
  <Text text="{= %{@$ui5.node.isExpanded} }"/>
28899
30055
  <Text text="{= %{@$ui5.node.level} }"/>
28900
30056
  <Text id="id" text="{ID}"/>
@@ -28913,7 +30069,7 @@ sap.ui.define([
28913
30069
  this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
28914
30070
  + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
28915
30071
  + ",NodeProperty='ID',Levels=1)"
28916
- + "&$select=AGE,DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=5", {
30072
+ + "&$select=AGE,DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=7", {
28917
30073
  "@odata.count" : "2",
28918
30074
  value : [{
28919
30075
  AGE : 60,
@@ -28939,17 +30095,14 @@ sap.ui.define([
28939
30095
  "/EMPLOYEES('9')"
28940
30096
  ], [
28941
30097
  [false, 1, "0", "", "Alpha", 60],
28942
- [undefined, 1, "9", "", "Omega", 69],
28943
- ["", "", "", "", "", ""],
28944
- ["", "", "", "", "", ""],
28945
- ["", "", "", "", "", ""]
30098
+ [undefined, 1, "9", "", "Omega", 69]
28946
30099
  ]);
28947
30100
  const oAlpha = oTable.getRows()[0].getBindingContext();
28948
30101
  const oOmega = oTable.getRows()[1].getBindingContext();
28949
30102
 
28950
30103
  this.expectRequest("EMPLOYEES?$apply=descendants($root/EMPLOYEES,OrgChart,ID"
28951
30104
  + ",filter(ID eq '0'),1)"
28952
- + "&$select=AGE,DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=5", {
30105
+ + "&$select=AGE,DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=7", {
28953
30106
  "@odata.count" : "3",
28954
30107
  value : [{
28955
30108
  AGE : 55,
@@ -28990,71 +30143,120 @@ sap.ui.define([
28990
30143
  [undefined, 2, "3", "0", "Lambda", 57],
28991
30144
  [undefined, 1, "9", "", "Omega", 69]
28992
30145
  ]);
28993
- const oBeta = oTable.getRows()[1].getBindingContext();
28994
30146
 
28995
- this.expectRequest("EMPLOYEES?$apply=descendants($root/EMPLOYEES,OrgChart,ID"
28996
- + ",filter(ID eq '1'),1)"
28997
- + "&$select=AGE,DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=5", {
28998
- "@odata.count" : "2",
28999
- value : [{
29000
- AGE : 41,
29001
- DrillState : "leaf",
29002
- ID : "1.1",
29003
- MANAGER_ID : "1",
29004
- Name : "Gamma"
29005
- }, {
29006
- AGE : 42,
29007
- DrillState : "leaf",
29008
- ID : "1.2",
29009
- MANAGER_ID : "1",
29010
- Name : "Zeta"
29011
- }]
29012
- })
29013
- .expectChange("id", [,, "1.1", "1.2", "2"]);
30147
+ const oExpandBetaResponse = {
30148
+ "@odata.count" : "2",
30149
+ value : [{
30150
+ AGE : 41,
30151
+ DrillState : "leaf",
30152
+ ID : "1.1",
30153
+ MANAGER_ID : "1",
30154
+ Name : "Gamma"
30155
+ }, {
30156
+ AGE : 42,
30157
+ DrillState : "leaf",
30158
+ ID : "1.2",
30159
+ MANAGER_ID : "1",
30160
+ Name : "Zeta"
30161
+ }]
30162
+ };
30163
+ if (bExpandCollapseBeta) {
30164
+ const oBeta = oTable.getRows()[1].getBindingContext();
29014
30165
 
29015
- oBeta.expand();
30166
+ this.expectRequest("EMPLOYEES?$apply=descendants($root/EMPLOYEES,OrgChart,ID"
30167
+ + ",filter(ID eq '1'),1)"
30168
+ + "&$select=AGE,DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=7",
30169
+ oExpandBetaResponse)
30170
+ .expectChange("id", [,, "1.1", "1.2", "2", "3", "9"]);
29016
30171
 
29017
- await this.waitForChanges(assert, "expand 1 (Beta)");
30172
+ oBeta.expand();
29018
30173
 
29019
- checkTable("after expand 1 (Beta)", assert, oTable, [
29020
- "/EMPLOYEES('0')",
29021
- "/EMPLOYEES('1')",
29022
- "/EMPLOYEES('1.1')",
29023
- "/EMPLOYEES('1.2')",
29024
- "/EMPLOYEES('2')",
29025
- "/EMPLOYEES('3')",
29026
- "/EMPLOYEES('9')"
29027
- ], [
29028
- [true, 1, "0", "", "Alpha", 60],
29029
- [true, 2, "1", "0", "Beta", 55],
29030
- [undefined, 3, "1.1", "1", "Gamma", 41],
29031
- [undefined, 3, "1.2", "1", "Zeta", 42],
29032
- [undefined, 2, "2", "0", "Kappa", 56]
29033
- ]);
30174
+ await this.waitForChanges(assert, "expand 1 (Beta)");
29034
30175
 
29035
- this.expectChange("id", [,, "2", "3", "9"]);
30176
+ checkTable("after expand 1 (Beta)", assert, oTable, [
30177
+ "/EMPLOYEES('0')",
30178
+ "/EMPLOYEES('1')",
30179
+ "/EMPLOYEES('1.1')",
30180
+ "/EMPLOYEES('1.2')",
30181
+ "/EMPLOYEES('2')",
30182
+ "/EMPLOYEES('3')",
30183
+ "/EMPLOYEES('9')"
30184
+ ], [
30185
+ [true, 1, "0", "", "Alpha", 60],
30186
+ [true, 2, "1", "0", "Beta", 55],
30187
+ [undefined, 3, "1.1", "1", "Gamma", 41],
30188
+ [undefined, 3, "1.2", "1", "Zeta", 42],
30189
+ [undefined, 2, "2", "0", "Kappa", 56],
30190
+ [undefined, 2, "3", "0", "Lambda", 57],
30191
+ [undefined, 1, "9", "", "Omega", 69]
30192
+ ]);
29036
30193
 
29037
- oBeta.collapse();
30194
+ this.expectChange("id", [,, "2", "3", "9"]);
29038
30195
 
29039
- await this.waitForChanges(assert, "collapse 1 (Beta)");
30196
+ oBeta.collapse();
29040
30197
 
29041
- checkTable("after collapse 1 (Beta)", assert, oTable, [
29042
- "/EMPLOYEES('0')",
29043
- "/EMPLOYEES('1')",
29044
- "/EMPLOYEES('2')",
29045
- "/EMPLOYEES('3')",
29046
- "/EMPLOYEES('9')"
29047
- ], [
29048
- [true, 1, "0", "", "Alpha", 60],
29049
- [false, 2, "1", "0", "Beta", 55],
29050
- [undefined, 2, "2", "0", "Kappa", 56],
29051
- [undefined, 2, "3", "0", "Lambda", 57],
29052
- [undefined, 1, "9", "", "Omega", 69]
29053
- ]);
30198
+ await this.waitForChanges(assert, "collapse 1 (Beta)");
30199
+
30200
+ checkTable("after collapse 1 (Beta)", assert, oTable, [
30201
+ "/EMPLOYEES('0')",
30202
+ "/EMPLOYEES('1')",
30203
+ "/EMPLOYEES('2')",
30204
+ "/EMPLOYEES('3')",
30205
+ "/EMPLOYEES('9')"
30206
+ ], [
30207
+ [true, 1, "0", "", "Alpha", 60],
30208
+ [false, 2, "1", "0", "Beta", 55],
30209
+ [undefined, 2, "2", "0", "Kappa", 56],
30210
+ [undefined, 2, "3", "0", "Lambda", 57],
30211
+ [undefined, 1, "9", "", "Omega", 69]
30212
+ ]);
30213
+ } // end if (bExpandCollapseBeta)
29054
30214
 
29055
30215
  if (bMoveCollapsed) {
29056
30216
  this.expectChange("id", [, "9"]);
29057
30217
  oAlpha.collapse();
30218
+ } else { // "A failed move must not leave the node collapsed"
30219
+ const oBeta = oTable.getRows()[1].getBindingContext();
30220
+
30221
+ this.expectEvents(assert, "sap.ui.model.odata.v4.ODataListBinding: /EMPLOYEES", [])
30222
+ .expectRequest({
30223
+ headers : {
30224
+ Prefer : "return=minimal"
30225
+ },
30226
+ method : "PATCH",
30227
+ url : "EMPLOYEES('0')",
30228
+ payload : {
30229
+ "EMPLOYEE_2_MANAGER@odata.bind" : "EMPLOYEES('9')"
30230
+ }
30231
+ }, createErrorInsideBatch());
30232
+
30233
+ await Promise.all([
30234
+ oAlpha.move({parent : oOmega}).then(mustFail(assert), function (oError) {
30235
+ assert.strictEqual(oError.message, "Request intentionally failed");
30236
+ }), // (JIRA: CPOUI5ODATAV4-2343)
30237
+ this.waitForChanges(assert, "move 0 (Alpha) to 9 (Omega) *FAILS*")
30238
+ ]);
30239
+
30240
+ this.expectEvents(assert, "sap.ui.model.odata.v4.ODataListBinding: /EMPLOYEES", [
30241
+ [, "change", {reason : "change"}] // caused by ODLB#getAllCurrentContexts
30242
+ ]);
30243
+ checkTable("after failed move", assert, oTable, [
30244
+ "/EMPLOYEES('0')",
30245
+ "/EMPLOYEES('1')",
30246
+ "/EMPLOYEES('2')",
30247
+ "/EMPLOYEES('3')",
30248
+ "/EMPLOYEES('9')"
30249
+ ], [
30250
+ [true, 1, "0", "", "Alpha", 60],
30251
+ [false, 2, "1", "0", "Beta", 55],
30252
+ [undefined, 2, "2", "0", "Kappa", 56],
30253
+ [undefined, 2, "3", "0", "Lambda", 57],
30254
+ [undefined, 1, "9", "", "Omega", 69]
30255
+ ]);
30256
+ assert.strictEqual(oTable.getRows()[1].getBindingContext(), oBeta, "unchanged");
30257
+
30258
+ // wait for UI changes caused by "change" event above
30259
+ await resolveLater(undefined, /*iDelay*/1);
29058
30260
  }
29059
30261
 
29060
30262
  this.expectEvents(assert, "sap.ui.model.odata.v4.ODataListBinding: /EMPLOYEES", [
@@ -29100,9 +30302,254 @@ sap.ui.define([
29100
30302
  [undefined, 3, "2", "0", "Kappa", 56],
29101
30303
  [undefined, 3, "3", "0", "Lambda", 57]
29102
30304
  ]);
30305
+ const oBeta = oTable.getRows()[2].getBindingContext();
30306
+ const oKappa = oTable.getRows()[3].getBindingContext();
30307
+
30308
+ const iBatchNo = this.iBatchNo + 1; // don't care about exact no., but use twice below
30309
+ this.expectEvents(assert, "sap.ui.model.odata.v4.ODataListBinding: /EMPLOYEES", [
30310
+ [, "change", {reason : "change"}]
30311
+ ])
30312
+ .expectRequest({
30313
+ batchNo : iBatchNo,
30314
+ headers : {
30315
+ Prefer : "return=minimal"
30316
+ },
30317
+ method : "PATCH",
30318
+ url : "EMPLOYEES('2')",
30319
+ payload : {
30320
+ "EMPLOYEE_2_MANAGER@odata.bind" : "EMPLOYEES('1')"
30321
+ }
30322
+ }) // 204 No Content
30323
+ .expectChange("id", [,,,, "1.1", "1.2", "3"]);
30324
+ if (!bExpandCollapseBeta) {
30325
+ this.expectRequest({
30326
+ batchNo : iBatchNo,
30327
+ url : "EMPLOYEES?$apply=descendants($root/EMPLOYEES,OrgChart,ID"
30328
+ + ",filter(ID eq '1'),1)"
30329
+ + "&$select=AGE,DrillState,ID,MANAGER_ID,Name&$count=true"
30330
+ + "&$filter=not (ID eq '2')&$skip=0&$top=6"
30331
+ }, oExpandBetaResponse);
30332
+ }
30333
+
30334
+ await Promise.all([
30335
+ oKappa.move({parent : oBeta}),
30336
+ this.waitForChanges(assert, "move 2 (Kappa) to collapsed 1 (Beta)")
30337
+ ]);
30338
+
30339
+ checkTable("after move 2 (Kappa) to collapsed 1 (Beta)", assert, oTable, [
30340
+ "/EMPLOYEES('9')",
30341
+ "/EMPLOYEES('0')",
30342
+ "/EMPLOYEES('1')",
30343
+ "/EMPLOYEES('2')",
30344
+ "/EMPLOYEES('1.1')",
30345
+ "/EMPLOYEES('1.2')",
30346
+ "/EMPLOYEES('3')"
30347
+ ], [
30348
+ [true, 1, "9", "", "Omega", 69],
30349
+ [true, 2, "0", ""/*TODO "9"*/, "Alpha", 60],
30350
+ [true, 3, "1", "0", "Beta", 55],
30351
+ [undefined, 4, "2", "0"/*TODO "1"*/, "Kappa", 56],
30352
+ [undefined, 4, "1.1", "1", "Gamma", 41],
30353
+ [undefined, 4, "1.2", "1", "Zeta", 42],
30354
+ [undefined, 3, "3", "0", "Lambda", 57]
30355
+ ]);
30356
+
30357
+ // code under test
30358
+ assert.strictEqual(oBeta.isAncestorOf(oKappa), true, "JIRA: CPOUI5ODATAV4-2337");
30359
+ assert.strictEqual(oOmega.isAncestorOf(oKappa), true, "JIRA: CPOUI5ODATAV4-2337");
30360
+ assert.strictEqual(oKappa.isAncestorOf(oOmega), false, "JIRA: CPOUI5ODATAV4-2337");
30361
+
30362
+ // code under test
30363
+ assert.strictEqual(oKappa.getParent(), oBeta, "JIRA: CPOUI5ODATAV4-2323");
30364
+ assert.strictEqual(oBeta.getParent(), oAlpha, "JIRA: CPOUI5ODATAV4-2323");
30365
+ assert.strictEqual(oAlpha.getParent(), oOmega, "JIRA: CPOUI5ODATAV4-2323");
30366
+ assert.strictEqual(oOmega.getParent(), null, "JIRA: CPOUI5ODATAV4-2323");
30367
+ });
29103
30368
  });
29104
30369
  });
29105
30370
 
30371
+ //*********************************************************************************************
30372
+ // Scenario: Show the first level of a recursive hierarchy ("Alpha", "Omega"), expand "Alpha".
30373
+ // Scroll to "Delta". Request side effects for the list binding. The parent node will not
30374
+ // anymore have a context in the list binding.
30375
+ // Determine the parent node of "Delta" with #getParent. It is not available at the moment.
30376
+ // Try to request the parent node of "Alpha" and "Delta".
30377
+ // JIRA: CPOUI5ODATAV4-2342
30378
+ QUnit.test("get and request Parent after requestSideEffects", async function (assert) {
30379
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
30380
+ const sView = `
30381
+ <t:Table id="table" rows="{path : '/EMPLOYEES',
30382
+ parameters : {
30383
+ $$aggregation : {hierarchyQualifier : 'OrgChart'}
30384
+ }}" threshold="0" visibleRowCount="2">
30385
+ <Text text="{= %{@$ui5.node.isExpanded} }"/>
30386
+ <Text text="{= %{@$ui5.node.level} }"/>
30387
+ <Text id="id" text="{ID}"/>
30388
+ <Text text="{Name}"/>
30389
+ </t:Table>`;
30390
+
30391
+ // 0 Alpha
30392
+ // 1 Beta
30393
+ // 2 Gamma
30394
+ // 3 Delta
30395
+ // 4 Epsilon
30396
+ // 9 Omega
30397
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
30398
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
30399
+ + ",NodeProperty='ID',Levels=1)"
30400
+ + "&$select=DrillState,ID,Name&$count=true&$skip=0&$top=2", {
30401
+ "@odata.count" : "2",
30402
+ value : [{
30403
+ DrillState : "collapsed",
30404
+ ID : "0",
30405
+ Name : "Alpha"
30406
+ }, {
30407
+ DrillState : "leaf",
30408
+ ID : "9",
30409
+ Name : "Omega"
30410
+ }]
30411
+ })
30412
+ .expectChange("id", ["0", "9"]);
30413
+
30414
+ await this.createView(assert, sView, oModel);
30415
+
30416
+ const oTable = this.oView.byId("table");
30417
+ checkTable("initial page", assert, oTable, [
30418
+ "/EMPLOYEES('0')",
30419
+ "/EMPLOYEES('9')"
30420
+ ], [
30421
+ [false, 1, "0", "Alpha"],
30422
+ [undefined, 1, "9", "Omega"]
30423
+ ]);
30424
+ const oAlpha = oTable.getRows()[0].getBindingContext();
30425
+
30426
+ this.expectRequest("EMPLOYEES?$apply=descendants($root/EMPLOYEES,OrgChart,ID"
30427
+ + ",filter(ID eq '0'),1)"
30428
+ + "&$select=DrillState,ID,Name&$count=true&$skip=0&$top=2", {
30429
+ "@odata.count" : "4",
30430
+ value : [{
30431
+ DrillState : "leaf",
30432
+ ID : "1",
30433
+ Name : "Beta"
30434
+ }, {
30435
+ DrillState : "leaf",
30436
+ ID : "2",
30437
+ Name : "Gamma"
30438
+ }]
30439
+ })
30440
+ .expectChange("id", [, "1"]);
30441
+
30442
+ oAlpha.expand();
30443
+
30444
+ await this.waitForChanges(assert, "expand 0 (Alpha)");
30445
+
30446
+ checkTable("after expand 0 (Alpha)", assert, oTable, [
30447
+ "/EMPLOYEES('0')",
30448
+ "/EMPLOYEES('1')",
30449
+ "/EMPLOYEES('2')",
30450
+ "/EMPLOYEES('9')"
30451
+ ], [
30452
+ [true, 1, "0", "Alpha"],
30453
+ [undefined, 2, "1", "Beta"]
30454
+ ], 6);
30455
+
30456
+ this.expectRequest("EMPLOYEES?$apply=descendants($root/EMPLOYEES,OrgChart,ID"
30457
+ + ",filter(ID eq '0'),1)"
30458
+ + "&$select=DrillState,ID,Name&$skip=2&$top=2", {
30459
+ value : [{
30460
+ DrillState : "leaf",
30461
+ ID : "3",
30462
+ Name : "Delta"
30463
+ }, {
30464
+ DrillState : "leaf",
30465
+ ID : "4",
30466
+ Name : "Epsilon"
30467
+ }]
30468
+ })
30469
+ .expectChange("id", [,,, "3", "4"]);
30470
+
30471
+ oTable.setFirstVisibleRow(3); // scroll to "Delta"
30472
+
30473
+ await this.waitForChanges(assert, "setFirstVisibleRow to 3 (Delta)");
30474
+
30475
+ checkTable("after setFirstVisibleRow", assert, oTable, [
30476
+ "/EMPLOYEES('0')",
30477
+ "/EMPLOYEES('1')",
30478
+ "/EMPLOYEES('2')",
30479
+ "/EMPLOYEES('3')",
30480
+ "/EMPLOYEES('4')",
30481
+ "/EMPLOYEES('9')"
30482
+ ], [
30483
+ [undefined, 2, "3", "Delta"],
30484
+ [undefined, 2, "4", "Epsilon"]
30485
+ ]);
30486
+ const oDelta = oTable.getRows()[0].getBindingContext();
30487
+
30488
+ this.expectRequest("EMPLOYEES?$select=ID,Name&$filter=ID eq '3' or ID eq '4'"
30489
+ + "&$top=2", {
30490
+ value : [{
30491
+ DrillState : "leaf",
30492
+ ID : "3",
30493
+ Name : "Delta"
30494
+ }, {
30495
+ DrillState : "leaf",
30496
+ ID : "4",
30497
+ Name : "Epsilon"
30498
+ }]
30499
+ });
30500
+
30501
+ // code under test
30502
+ assert.strictEqual(oAlpha.getParent(), null);
30503
+ assert.strictEqual(await oAlpha.requestParent(), null);
30504
+
30505
+ await Promise.all([
30506
+ oDelta.getBinding().getHeaderContext().requestSideEffects(["Name"]),
30507
+ this.waitForChanges(assert, "request side effects for name")
30508
+ ]);
30509
+
30510
+ checkTable("after requestSideEffects", assert, oTable, [
30511
+ "/EMPLOYEES('3')",
30512
+ "/EMPLOYEES('4')"
30513
+ ], [
30514
+ [undefined, 2, "3", "Delta"],
30515
+ [undefined, 2, "4", "Epsilon"]
30516
+ ], 6);
30517
+
30518
+ // code under test
30519
+ assert.strictEqual(oDelta.getParent(), undefined, "JIRA: CPOUI5ODATAV4-2323");
30520
+
30521
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
30522
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
30523
+ + ",NodeProperty='ID',Levels=1)"
30524
+ + "&$select=DrillState,ID,Name&$skip=0&$top=1", {
30525
+ value : [{
30526
+ DrillState : "collapsed",
30527
+ ID : "0",
30528
+ Name : "Alpha"
30529
+ }]
30530
+ })
30531
+ .expectChange("id", ["0", "9"]);
30532
+
30533
+ // code under test
30534
+ const oResult = await oDelta.requestParent();
30535
+
30536
+ assert.strictEqual(oAlpha.getModel(), undefined, "Alpha is destroyed");
30537
+ assert.notStrictEqual(oResult, oAlpha);
30538
+ assert.strictEqual(oResult.getPath(), oAlpha.getPath());
30539
+ assert.strictEqual(oResult.iIndex, oAlpha.iIndex);
30540
+ assert.strictEqual(oDelta.getParent(), oResult,
30541
+ "#getParent and #requestParent must deliver the same context");
30542
+
30543
+ checkTable("after requestParent", assert, oTable, [
30544
+ "/EMPLOYEES('0')",
30545
+ "/EMPLOYEES('3')",
30546
+ "/EMPLOYEES('4')"
30547
+ ], [
30548
+ [undefined, 2, "3", "Delta"],
30549
+ [undefined, 2, "4", "Epsilon"]
30550
+ ], 6);
30551
+ });
30552
+
29106
30553
  //*********************************************************************************************
29107
30554
  // Scenario: Show the single root node of a recursive hierarchy and expand it. Not all children
29108
30555
  // are loaded, but some placeholders remain. Create two new child nodes underneath the root.
@@ -41432,7 +42879,7 @@ sap.ui.define([
41432
42879
  }
41433
42880
 
41434
42881
  // code under test
41435
- Configuration.setSecurityTokenHandlers([
42882
+ Security.setSecurityTokenHandlers([
41436
42883
  securityTokenHandler0,
41437
42884
  securityTokenHandler1,
41438
42885
  securityTokenHandler2
@@ -41456,7 +42903,7 @@ sap.ui.define([
41456
42903
 
41457
42904
  return that.waitForChanges(assert);
41458
42905
  }).finally(function () {
41459
- Configuration.setSecurityTokenHandlers([]);
42906
+ Security.setSecurityTokenHandlers([]);
41460
42907
  });
41461
42908
  });
41462
42909
  });
@@ -42292,7 +43739,8 @@ sap.ui.define([
42292
43739
  // BCP: 2080062941
42293
43740
  testXMLTemplating("BCP: 2080062941",
42294
43741
  "createSpecialCasesModel",
42295
- '<template:alias name="format" value="sap.ui.model.odata.v4.AnnotationHelper.format">\
43742
+ ' template:require="{\'AnnotationHelper\':\'sap/ui/model/odata/v4/AnnotationHelper\'}">\
43743
+ <template:alias name="format" value="AnnotationHelper.format">\
42296
43744
  <template:repeat \
42297
43745
  list="{meta>/special.cases.EntityWithUnsupportedEdmTypes/@com.sap.vocabularies.UI.v1.SelectionFields}"\
42298
43746
  var="field">\
@@ -43256,7 +44704,8 @@ sap.ui.define([
43256
44704
  // JIRA: CPOUI5ODATAV4-104
43257
44705
  testXMLTemplating("AnnotationHelper#value on properties",
43258
44706
  "createSpecialCasesModel",
43259
- '<template:alias name="value" value="sap.ui.model.odata.v4.AnnotationHelper.value">\
44707
+ ' template:require="{\'AnnotationHelper\':\'sap/ui/model/odata/v4/AnnotationHelper\'}">\
44708
+ <template:alias name="value" value="AnnotationHelper.value">\
43260
44709
  <Input value="{meta>/Artists/Name@@value}"/>\
43261
44710
  <Input value="{meta>/Artists/BestFriend/IsActiveEntity@@value}"/>\
43262
44711
  <Input value="{meta>/Artists/Address/ZIP@@value}"/>\
@@ -43275,7 +44724,8 @@ sap.ui.define([
43275
44724
  // JIRA: CPOUI5ODATAV4-104
43276
44725
  testXMLTemplating("AnnotationHelper#value inside path object",
43277
44726
  "createSpecialCasesModel",
43278
- '<template:alias name="value" value="sap.ui.model.odata.v4.AnnotationHelper.value">\
44727
+ ' template:require="{\'AnnotationHelper\':\'sap/ui/model/odata/v4/AnnotationHelper\'}">\
44728
+ <template:alias name="value" value="AnnotationHelper.value">\
43279
44729
  <Input value="{meta>/Artists/@com.sap.vocabularies.UI.v1.SelectionFields/0/$PropertyPath@@value}"/>\
43280
44730
  <Input value="{meta>/Artists/@com.sap.vocabularies.UI.v1.SelectionFields/1/$PropertyPath@@value}"/>\
43281
44731
  <Input value="{meta>/Artists/ArtistID@com.sap.vocabularies.Common.v1.Text/$Path@@value}"/>\
@@ -43296,7 +44746,8 @@ sap.ui.define([
43296
44746
  // JIRA: CPOUI5ODATAV4-104
43297
44747
  testXMLTemplating("AnnotationHelper#format on properties",
43298
44748
  "createSpecialCasesModel",
43299
- '<template:alias name="format" value="sap.ui.model.odata.v4.AnnotationHelper.format">\
44749
+ ' template:require="{\'AnnotationHelper\':\'sap/ui/model/odata/v4/AnnotationHelper\'}">\
44750
+ <template:alias name="format" value="AnnotationHelper.format">\
43300
44751
  <Input value="{meta>/Artists/Name@@format}"/>\
43301
44752
  <Input value="{meta>/Artists/BestFriend/IsActiveEntity@@format}"/>\
43302
44753
  <Input value="{meta>/Artists/Address/ZIP@@format}"/>\
@@ -43320,7 +44771,8 @@ sap.ui.define([
43320
44771
  // JIRA: CPOUI5ODATAV4-104
43321
44772
  testXMLTemplating("AnnotationHelper#format inside path object",
43322
44773
  "createSpecialCasesModel",
43323
- '<template:alias name="format" value="sap.ui.model.odata.v4.AnnotationHelper.format">\
44774
+ ' template:require="{\'AnnotationHelper\':\'sap/ui/model/odata/v4/AnnotationHelper\'}">\
44775
+ <template:alias name="format" value="AnnotationHelper.format">\
43324
44776
  <Input value="{meta>/Artists/@com.sap.vocabularies.UI.v1.SelectionFields/0/$PropertyPath@@format}"/>\
43325
44777
  <Input value="{meta>/Artists/@com.sap.vocabularies.UI.v1.SelectionFields/1/$PropertyPath@@format}"/>\
43326
44778
  <Input value="{meta>/Artists/ArtistID@com.sap.vocabularies.Common.v1.Text/$Path@@format}"/>\