@openui5/sap.ui.core 1.117.1 → 1.119.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 (1096) hide show
  1. package/.eslintrc.json +9 -0
  2. package/THIRDPARTY.txt +2 -2
  3. package/package.json +1 -1
  4. package/src/jquery.sap.global.js +1 -1
  5. package/src/jquery.sap.properties.js +1 -1
  6. package/src/jquery.sap.resources.js +1 -1
  7. package/src/jquery.sap.script.js +1 -1
  8. package/src/jquery.sap.storage.js +3 -3
  9. package/src/sap/base/Event.js +1 -1
  10. package/src/sap/base/Eventing.js +1 -1
  11. package/src/sap/base/config.js +1 -1
  12. package/src/sap/base/i18n/LanguageTag.js +1 -1
  13. package/src/sap/base/i18n/Localization.js +58 -40
  14. package/src/sap/base/i18n/ResourceBundle.js +5 -0
  15. package/src/sap/base/i18n/date/TimezoneUtils.js +1 -1
  16. package/src/sap/base/util/UriParameters.js +26 -19
  17. package/src/sap/base/util/restricted/_CancelablePromise.js +1 -1
  18. package/src/sap/base/util/restricted/_castArray.js +1 -1
  19. package/src/sap/base/util/restricted/_compact.js +1 -1
  20. package/src/sap/base/util/restricted/_curry.js +1 -1
  21. package/src/sap/base/util/restricted/_debounce.js +1 -1
  22. package/src/sap/base/util/restricted/_difference.js +1 -1
  23. package/src/sap/base/util/restricted/_differenceBy.js +1 -1
  24. package/src/sap/base/util/restricted/_differenceWith.js +1 -1
  25. package/src/sap/base/util/restricted/_flatMap.js +1 -1
  26. package/src/sap/base/util/restricted/_flatMapDeep.js +1 -1
  27. package/src/sap/base/util/restricted/_flatMapDepth.js +1 -1
  28. package/src/sap/base/util/restricted/_flatten.js +1 -1
  29. package/src/sap/base/util/restricted/_flattenDeep.js +1 -1
  30. package/src/sap/base/util/restricted/_flattenDepth.js +1 -1
  31. package/src/sap/base/util/restricted/_intersection.js +1 -1
  32. package/src/sap/base/util/restricted/_intersectionBy.js +1 -1
  33. package/src/sap/base/util/restricted/_intersectionWith.js +1 -1
  34. package/src/sap/base/util/restricted/_isEqual.js +1 -1
  35. package/src/sap/base/util/restricted/_isEqualWith.js +1 -1
  36. package/src/sap/base/util/restricted/_isNil.js +1 -1
  37. package/src/sap/base/util/restricted/_max.js +1 -1
  38. package/src/sap/base/util/restricted/_merge.js +1 -1
  39. package/src/sap/base/util/restricted/_mergeWith.js +1 -1
  40. package/src/sap/base/util/restricted/_min.js +1 -1
  41. package/src/sap/base/util/restricted/_omit.js +1 -1
  42. package/src/sap/base/util/restricted/_pick.js +1 -1
  43. package/src/sap/base/util/restricted/_pickBy.js +1 -1
  44. package/src/sap/base/util/restricted/_throttle.js +1 -1
  45. package/src/sap/base/util/restricted/_toArray.js +1 -1
  46. package/src/sap/base/util/restricted/_union.js +1 -1
  47. package/src/sap/base/util/restricted/_unionBy.js +1 -1
  48. package/src/sap/base/util/restricted/_unionWith.js +1 -1
  49. package/src/sap/base/util/restricted/_uniq.js +1 -1
  50. package/src/sap/base/util/restricted/_uniqBy.js +1 -1
  51. package/src/sap/base/util/restricted/_uniqWith.js +1 -1
  52. package/src/sap/base/util/restricted/_without.js +1 -1
  53. package/src/sap/base/util/restricted/_xor.js +1 -1
  54. package/src/sap/base/util/restricted/_xorBy.js +1 -1
  55. package/src/sap/base/util/restricted/_xorWith.js +1 -1
  56. package/src/sap/base/util/restricted/_zipObject.js +1 -1
  57. package/src/sap/base/util/restricted/_zipObjectDeep.js +1 -1
  58. package/src/sap/ui/Device.js +3 -3
  59. package/src/sap/ui/Global.js +4 -4
  60. package/src/sap/ui/base/BindingInfo.js +25 -3
  61. package/src/sap/ui/base/BindingParser.js +2 -1
  62. package/src/sap/ui/base/Event.js +1 -1
  63. package/src/sap/ui/base/EventProvider.js +1 -1
  64. package/src/sap/ui/base/Interface.js +1 -1
  65. package/src/sap/ui/base/ManagedObject.js +8 -4
  66. package/src/sap/ui/base/ManagedObjectMetadata.js +4 -3
  67. package/src/sap/ui/base/Metadata.js +3 -3
  68. package/src/sap/ui/base/Object.js +1 -1
  69. package/src/sap/ui/base/ObjectPool.js +1 -1
  70. package/src/sap/ui/core/.library +9 -1
  71. package/src/sap/ui/core/AccessKeysEnablement.js +2 -2
  72. package/src/sap/ui/core/AnimationMode.js +1 -1
  73. package/src/sap/ui/core/BlockLayerUtils.js +1 -1
  74. package/src/sap/ui/core/BusyIndicator.js +2 -2
  75. package/src/sap/ui/core/Component.js +85 -61
  76. package/src/sap/ui/core/ComponentContainer.js +2 -2
  77. package/src/sap/ui/core/ComponentMetadata.js +1 -1
  78. package/src/sap/ui/core/ComponentSupport.js +1 -1
  79. package/src/sap/ui/core/Configuration.js +15 -179
  80. package/src/sap/ui/core/Control.js +22 -2
  81. package/src/sap/ui/core/Core.js +223 -128
  82. package/src/sap/ui/core/CustomData.js +1 -1
  83. package/src/sap/ui/core/CustomStyleClassSupport.js +3 -3
  84. package/src/sap/ui/core/DeclarativeSupport.js +1 -1
  85. package/src/sap/ui/core/Element.js +40 -4
  86. package/src/sap/ui/core/ElementMetadata.js +1 -1
  87. package/src/sap/ui/core/EnabledPropagator.js +1 -1
  88. package/src/sap/ui/core/EventBus.js +19 -2
  89. package/src/sap/ui/core/FocusHandler.js +3 -24
  90. package/src/sap/ui/core/Fragment.js +2 -2
  91. package/src/sap/ui/core/HTML.js +1 -1
  92. package/src/sap/ui/core/History.js +1 -1
  93. package/src/sap/ui/core/Icon.js +2 -2
  94. package/src/sap/ui/core/IndicationColorSupport.js +2 -2
  95. package/src/sap/ui/core/IntervalTrigger.js +1 -1
  96. package/src/sap/ui/core/InvisibleMessage.js +1 -1
  97. package/src/sap/ui/core/InvisibleRenderer.js +1 -1
  98. package/src/sap/ui/core/InvisibleText.js +4 -7
  99. package/src/sap/ui/core/Item.js +1 -1
  100. package/src/sap/ui/core/LabelEnablement.js +11 -4
  101. package/src/sap/ui/core/LayoutData.js +1 -1
  102. package/src/sap/ui/core/Lib.js +51 -55
  103. package/src/sap/ui/core/ListItem.js +1 -1
  104. package/src/sap/ui/core/LocalBusyIndicator.js +1 -1
  105. package/src/sap/ui/core/Locale.js +1 -1
  106. package/src/sap/ui/core/LocaleData.js +2 -2
  107. package/src/sap/ui/core/Manifest.js +1 -1
  108. package/src/sap/ui/core/Message.js +4 -4
  109. package/src/sap/ui/core/Messaging.js +471 -0
  110. package/src/sap/ui/core/Popup.js +3 -3
  111. package/src/sap/ui/core/RenderManager.js +15 -10
  112. package/src/sap/ui/core/Renderer.js +1 -1
  113. package/src/sap/ui/core/Rendering.js +4 -2
  114. package/src/sap/ui/core/ResizeHandler.js +15 -23
  115. package/src/sap/ui/core/ScrollBar.js +1 -1
  116. package/src/sap/ui/core/SeparatorItem.js +1 -1
  117. package/src/sap/ui/core/ShortcutHint.js +1 -1
  118. package/src/sap/ui/core/ShortcutHintsMixin.js +5 -5
  119. package/src/sap/ui/core/StashedControlSupport.js +4 -4
  120. package/src/sap/ui/core/StaticArea.js +66 -74
  121. package/src/sap/ui/core/Theming.js +99 -39
  122. package/src/sap/ui/core/Title.js +1 -1
  123. package/src/sap/ui/core/TooltipBase.js +1 -1
  124. package/src/sap/ui/core/UIArea.js +93 -24
  125. package/src/sap/ui/core/UIComponent.js +2 -2
  126. package/src/sap/ui/core/UIComponentMetadata.js +1 -1
  127. package/src/sap/ui/core/ValueStateSupport.js +2 -2
  128. package/src/sap/ui/core/VariantLayoutData.js +1 -1
  129. package/src/sap/ui/core/XMLComposite.js +4 -2
  130. package/src/sap/ui/core/XMLCompositeMetadata.js +1 -1
  131. package/src/sap/ui/core/_IconRegistry.js +3 -1
  132. package/src/sap/ui/core/boot.js +9 -0
  133. package/src/sap/ui/core/cache/CacheManager.js +22 -16
  134. package/src/sap/ui/core/cache/LRUPersistentCache.js +13 -7
  135. package/src/sap/ui/core/date/UI5Date.js +1 -1
  136. package/src/sap/ui/core/delegate/ItemNavigation.js +3 -3
  137. package/src/sap/ui/core/delegate/ScrollEnablement.js +1 -1
  138. package/src/sap/ui/core/dnd/DragAndDrop.js +1 -1
  139. package/src/sap/ui/core/dnd/DragDropBase.js +1 -1
  140. package/src/sap/ui/core/dnd/DragDropInfo.js +6 -6
  141. package/src/sap/ui/core/dnd/DragInfo.js +4 -4
  142. package/src/sap/ui/core/dnd/DropInfo.js +6 -6
  143. package/src/sap/ui/core/format/DateFormat.js +4 -0
  144. package/src/sap/ui/core/format/TimezoneUtil.js +1 -1
  145. package/src/sap/ui/core/getCompatibilityVersion.js +64 -0
  146. package/src/sap/ui/core/hyphenation/Hyphenation.js +1 -1
  147. package/src/sap/ui/core/library.js +26 -50
  148. package/src/sap/ui/core/message/ControlMessageProcessor.js +4 -4
  149. package/src/sap/ui/core/message/Message.js +14 -13
  150. package/src/sap/ui/core/message/MessageManager.js +36 -459
  151. package/src/sap/ui/core/message/MessageMixin.js +5 -5
  152. package/src/sap/ui/core/message/MessageParser.js +1 -1
  153. package/src/sap/ui/core/message/MessageProcessor.js +9 -9
  154. package/src/sap/ui/core/message/MessageType.js +53 -0
  155. package/src/sap/ui/core/messagebundle.properties +3 -0
  156. package/src/sap/ui/core/messagebundle_ar.properties +3 -3
  157. package/src/sap/ui/core/messagebundle_bg.properties +4 -4
  158. package/src/sap/ui/core/messagebundle_ca.properties +2 -2
  159. package/src/sap/ui/core/messagebundle_cs.properties +5 -5
  160. package/src/sap/ui/core/messagebundle_cy.properties +2 -2
  161. package/src/sap/ui/core/messagebundle_da.properties +4 -4
  162. package/src/sap/ui/core/messagebundle_de.properties +3 -3
  163. package/src/sap/ui/core/messagebundle_el.properties +11 -11
  164. package/src/sap/ui/core/messagebundle_en.properties +4 -4
  165. package/src/sap/ui/core/messagebundle_es.properties +18 -18
  166. package/src/sap/ui/core/messagebundle_es_MX.properties +1 -1
  167. package/src/sap/ui/core/messagebundle_et.properties +1 -1
  168. package/src/sap/ui/core/messagebundle_fi.properties +2 -2
  169. package/src/sap/ui/core/messagebundle_fr.properties +22 -22
  170. package/src/sap/ui/core/messagebundle_fr_CA.properties +1 -1
  171. package/src/sap/ui/core/messagebundle_hi.properties +3 -3
  172. package/src/sap/ui/core/messagebundle_hr.properties +7 -7
  173. package/src/sap/ui/core/messagebundle_hu.properties +11 -11
  174. package/src/sap/ui/core/messagebundle_id.properties +6 -6
  175. package/src/sap/ui/core/messagebundle_it.properties +58 -58
  176. package/src/sap/ui/core/messagebundle_iw.properties +6 -6
  177. package/src/sap/ui/core/messagebundle_ja.properties +1 -1
  178. package/src/sap/ui/core/messagebundle_kk.properties +2 -2
  179. package/src/sap/ui/core/messagebundle_ko.properties +7 -7
  180. package/src/sap/ui/core/messagebundle_lt.properties +1 -1
  181. package/src/sap/ui/core/messagebundle_lv.properties +6 -6
  182. package/src/sap/ui/core/messagebundle_ms.properties +6 -6
  183. package/src/sap/ui/core/messagebundle_nl.properties +13 -13
  184. package/src/sap/ui/core/messagebundle_no.properties +9 -9
  185. package/src/sap/ui/core/messagebundle_pl.properties +3 -3
  186. package/src/sap/ui/core/messagebundle_pt.properties +9 -9
  187. package/src/sap/ui/core/messagebundle_pt_PT.properties +1 -1
  188. package/src/sap/ui/core/messagebundle_ro.properties +3 -3
  189. package/src/sap/ui/core/messagebundle_ru.properties +8 -8
  190. package/src/sap/ui/core/messagebundle_sh.properties +1 -1
  191. package/src/sap/ui/core/messagebundle_sk.properties +3 -3
  192. package/src/sap/ui/core/messagebundle_sl.properties +10 -10
  193. package/src/sap/ui/core/messagebundle_sv.properties +1 -1
  194. package/src/sap/ui/core/messagebundle_th.properties +19 -19
  195. package/src/sap/ui/core/messagebundle_tr.properties +6 -6
  196. package/src/sap/ui/core/messagebundle_uk.properties +9 -9
  197. package/src/sap/ui/core/messagebundle_vi.properties +2 -2
  198. package/src/sap/ui/core/messagebundle_zh_CN.properties +3 -3
  199. package/src/sap/ui/core/messagebundle_zh_TW.properties +25 -25
  200. package/src/sap/ui/core/mvc/HTMLView.js +1 -1
  201. package/src/sap/ui/core/mvc/JSONView.js +1 -1
  202. package/src/sap/ui/core/mvc/JSView.js +1 -1
  203. package/src/sap/ui/core/mvc/TemplateView.js +1 -1
  204. package/src/sap/ui/core/mvc/View.js +3 -3
  205. package/src/sap/ui/core/mvc/XMLView.js +9 -2
  206. package/src/sap/ui/core/plugin/DeclarativeSupport.js +1 -1
  207. package/src/sap/ui/core/plugin/LessSupport.js +3 -3
  208. package/src/sap/ui/core/plugin/TemplatingSupport.js +1 -1
  209. package/src/sap/ui/core/postmessage/Bus.js +1 -1
  210. package/src/sap/ui/core/postmessage/confirmationDialog.js +1 -1
  211. package/src/sap/ui/core/routing/Router.js +7 -1
  212. package/src/sap/ui/core/routing/async/Route.js +1 -0
  213. package/src/sap/ui/core/routing/async/Target.js +5 -4
  214. package/src/sap/ui/core/routing/sync/Route.js +1 -0
  215. package/src/sap/ui/core/routing/sync/Target.js +3 -3
  216. package/src/sap/ui/core/rules/App.support.js +30 -1
  217. package/src/sap/ui/core/rules/Config.support.js +4 -0
  218. package/src/sap/ui/core/rules/CoreHelper.support.js +3 -3
  219. package/src/sap/ui/core/rules/Theming.support.js +4 -0
  220. package/src/sap/ui/core/search/OpenSearchProvider.js +1 -1
  221. package/src/sap/ui/core/search/SearchProvider.js +1 -1
  222. package/src/sap/ui/core/service/Service.js +1 -1
  223. package/src/sap/ui/core/service/ServiceFactory.js +1 -1
  224. package/src/sap/ui/core/service/ServiceFactoryRegistry.js +1 -1
  225. package/src/sap/ui/core/support/Plugin.js +25 -5
  226. package/src/sap/ui/core/support/Support.js +38 -6
  227. package/src/sap/ui/core/support/ToolsAPI.js +14 -20
  228. package/src/sap/ui/core/support/controls/InteractionTree.js +0 -4
  229. package/src/sap/ui/core/support/plugins/Breakpoint.js +4 -6
  230. package/src/sap/ui/core/support/plugins/ControlTree.js +40 -24
  231. package/src/sap/ui/core/support/plugins/Debugging.js +10 -9
  232. package/src/sap/ui/core/support/plugins/Interaction.js +12 -13
  233. package/src/sap/ui/core/support/plugins/LocalStorage.js +1 -3
  234. package/src/sap/ui/core/support/plugins/Performance.js +1 -3
  235. package/src/sap/ui/core/support/plugins/Selector.js +2 -2
  236. package/src/sap/ui/core/support/plugins/TechInfo.js +32 -42
  237. package/src/sap/ui/core/support/plugins/Trace.js +1 -1
  238. package/src/sap/ui/core/support/plugins/ViewInfo.js +32 -16
  239. package/src/sap/ui/core/support/techinfo/TechnicalInfo.js +8 -6
  240. package/src/sap/ui/core/support/usage/EventBroadcaster.js +1 -1
  241. package/src/sap/ui/core/themes/base/base.less +275 -269
  242. package/src/sap/ui/core/themes/base/fonts/SAP-icons.ttf +0 -0
  243. package/src/sap/ui/core/themes/base/fonts/SAP-icons.woff2 +0 -0
  244. package/src/sap/ui/core/themes/base/global.less +8 -8
  245. package/src/sap/ui/core/theming/Parameters.js +4 -5
  246. package/src/sap/ui/core/theming/ThemeHelper.js +100 -1
  247. package/src/sap/ui/core/theming/ThemeManager.js +32 -31
  248. package/src/sap/ui/core/tmpl/DOMAttribute.js +1 -1
  249. package/src/sap/ui/core/tmpl/DOMElement.js +1 -1
  250. package/src/sap/ui/core/tmpl/HandlebarsTemplate.js +1 -1
  251. package/src/sap/ui/core/tmpl/Template.js +1 -1
  252. package/src/sap/ui/core/tmpl/TemplateControl.js +4 -2
  253. package/src/sap/ui/core/util/AsyncHintsHelper.js +1 -1
  254. package/src/sap/ui/core/util/Export.js +1 -1
  255. package/src/sap/ui/core/util/ExportCell.js +1 -1
  256. package/src/sap/ui/core/util/ExportColumn.js +1 -1
  257. package/src/sap/ui/core/util/ExportRow.js +1 -1
  258. package/src/sap/ui/core/util/ExportType.js +1 -1
  259. package/src/sap/ui/core/util/ExportTypeCSV.js +1 -1
  260. package/src/sap/ui/core/util/File.js +1 -1
  261. package/src/sap/ui/core/util/LibraryInfo.js +1 -1
  262. package/src/sap/ui/core/util/MockServer.js +1 -1
  263. package/src/sap/ui/core/util/PasteHelper.js +1 -1
  264. package/src/sap/ui/core/util/XMLPreprocessor.js +53 -29
  265. package/src/sap/ui/core/util/reflection/BaseTreeModifier.js +27 -4
  266. package/src/sap/ui/core/util/reflection/JsControlTreeModifier.js +55 -30
  267. package/src/sap/ui/core/util/reflection/XmlTreeModifier.js +54 -48
  268. package/src/sap/ui/core/util/serializer/HTMLViewSerializer.js +2 -2
  269. package/src/sap/ui/core/util/serializer/Serializer.js +3 -3
  270. package/src/sap/ui/core/util/serializer/ViewSerializer.js +27 -10
  271. package/src/sap/ui/core/util/serializer/XMLViewSerializer.js +2 -2
  272. package/src/sap/ui/core/util/serializer/delegate/Delegate.js +1 -1
  273. package/src/sap/ui/core/util/serializer/delegate/HTML.js +1 -1
  274. package/src/sap/ui/core/util/serializer/delegate/XML.js +1 -1
  275. package/src/sap/ui/core/webc/WebComponent.js +659 -0
  276. package/src/sap/ui/core/webc/WebComponentMetadata.js +253 -0
  277. package/src/sap/ui/core/webc/WebComponentRenderer.js +323 -0
  278. package/src/sap/ui/core/ws/ReadyState.js +1 -1
  279. package/src/sap/ui/core/ws/SapPcpWebSocket.js +1 -1
  280. package/src/sap/ui/core/ws/WebSocket.js +1 -1
  281. package/src/sap/ui/debug/ControlTree.js +8 -7
  282. package/src/sap/ui/debug/DebugEnv.js +18 -9
  283. package/src/sap/ui/debug/PropertyList.js +3 -3
  284. package/src/sap/ui/dom/jquery/control.js +3 -4
  285. package/src/sap/ui/events/F6Navigation.js +2 -1
  286. package/src/sap/ui/model/Binding.js +6 -6
  287. package/src/sap/ui/model/ClientModel.js +33 -1
  288. package/src/sap/ui/model/ClientPropertyBinding.js +20 -4
  289. package/src/sap/ui/model/CompositeDataState.js +1 -1
  290. package/src/sap/ui/model/CompositeType.js +1 -1
  291. package/src/sap/ui/model/Context.js +1 -1
  292. package/src/sap/ui/model/DataState.js +1 -1
  293. package/src/sap/ui/model/Filter.js +1 -1
  294. package/src/sap/ui/model/ManagedObjectBindingSupport.js +4 -4
  295. package/src/sap/ui/model/MetaModel.js +1 -1
  296. package/src/sap/ui/model/Model.js +4 -4
  297. package/src/sap/ui/model/SelectionModel.js +1 -1
  298. package/src/sap/ui/model/SimpleType.js +1 -1
  299. package/src/sap/ui/model/TreeAutoExpandMode.js +1 -1
  300. package/src/sap/ui/model/Type.js +1 -1
  301. package/src/sap/ui/model/controlhelper/TreeBindingProxy.js +27 -13
  302. package/src/sap/ui/model/json/JSONModel.js +2 -3
  303. package/src/sap/ui/model/message/MessageModel.js +3 -7
  304. package/src/sap/ui/model/odata/ODataAnnotations.js +1 -1
  305. package/src/sap/ui/model/odata/ODataListBinding.js +24 -0
  306. package/src/sap/ui/model/odata/ODataMessageParser.js +4 -4
  307. package/src/sap/ui/model/odata/ODataMetaModel.js +1 -1
  308. package/src/sap/ui/model/odata/ODataMetadata.js +1 -1
  309. package/src/sap/ui/model/odata/ODataModel.js +1 -1
  310. package/src/sap/ui/model/odata/ODataTreeBindingFlat.js +6 -0
  311. package/src/sap/ui/model/odata/type/Boolean.js +1 -1
  312. package/src/sap/ui/model/odata/type/Byte.js +1 -1
  313. package/src/sap/ui/model/odata/type/Currency.js +1 -1
  314. package/src/sap/ui/model/odata/type/Date.js +1 -1
  315. package/src/sap/ui/model/odata/type/DateTime.js +1 -1
  316. package/src/sap/ui/model/odata/type/DateTimeBase.js +1 -1
  317. package/src/sap/ui/model/odata/type/DateTimeOffset.js +7 -2
  318. package/src/sap/ui/model/odata/type/DateTimeWithTimezone.js +1 -2
  319. package/src/sap/ui/model/odata/type/Decimal.js +1 -1
  320. package/src/sap/ui/model/odata/type/Double.js +1 -1
  321. package/src/sap/ui/model/odata/type/Guid.js +1 -1
  322. package/src/sap/ui/model/odata/type/Int.js +1 -1
  323. package/src/sap/ui/model/odata/type/Int16.js +1 -1
  324. package/src/sap/ui/model/odata/type/Int32.js +1 -1
  325. package/src/sap/ui/model/odata/type/Int64.js +1 -1
  326. package/src/sap/ui/model/odata/type/ODataType.js +2 -3
  327. package/src/sap/ui/model/odata/type/Raw.js +1 -1
  328. package/src/sap/ui/model/odata/type/SByte.js +1 -1
  329. package/src/sap/ui/model/odata/type/Single.js +1 -1
  330. package/src/sap/ui/model/odata/type/Stream.js +1 -1
  331. package/src/sap/ui/model/odata/type/String.js +1 -1
  332. package/src/sap/ui/model/odata/type/Time.js +1 -1
  333. package/src/sap/ui/model/odata/type/TimeOfDay.js +6 -2
  334. package/src/sap/ui/model/odata/type/Unit.js +1 -1
  335. package/src/sap/ui/model/odata/v2/Context.js +13 -5
  336. package/src/sap/ui/model/odata/v2/ODataAnnotations.js +1 -1
  337. package/src/sap/ui/model/odata/v2/ODataListBinding.js +108 -59
  338. package/src/sap/ui/model/odata/v2/ODataModel.js +25 -20
  339. package/src/sap/ui/model/odata/v2/ODataTreeBinding.js +33 -6
  340. package/src/sap/ui/model/odata/v4/Context.js +83 -23
  341. package/src/sap/ui/model/odata/v4/ODataBinding.js +13 -4
  342. package/src/sap/ui/model/odata/v4/ODataContextBinding.js +162 -33
  343. package/src/sap/ui/model/odata/v4/ODataListBinding.js +151 -48
  344. package/src/sap/ui/model/odata/v4/ODataMetaModel.js +1 -1
  345. package/src/sap/ui/model/odata/v4/ODataModel.js +21 -14
  346. package/src/sap/ui/model/odata/v4/ODataParentBinding.js +4 -2
  347. package/src/sap/ui/model/odata/v4/ODataPropertyBinding.js +12 -11
  348. package/src/sap/ui/model/odata/v4/lib/_AggregationCache.js +234 -31
  349. package/src/sap/ui/model/odata/v4/lib/_AggregationHelper.js +3 -5
  350. package/src/sap/ui/model/odata/v4/lib/_Cache.js +180 -76
  351. package/src/sap/ui/model/odata/v4/lib/_Helper.js +36 -24
  352. package/src/sap/ui/model/odata/v4/lib/_Parser.js +3 -0
  353. package/src/sap/ui/model/odata/v4/lib/_Requestor.js +17 -7
  354. package/src/sap/ui/model/odata/v4/lib/_V2MetadataConverter.js +1 -1
  355. package/src/sap/ui/model/odata/v4/lib/_V2Requestor.js +28 -35
  356. package/src/sap/ui/model/odata/v4/ts.js +44 -0
  357. package/src/sap/ui/model/resource/ResourceModel.js +1 -1
  358. package/src/sap/ui/model/type/Boolean.js +1 -1
  359. package/src/sap/ui/model/type/Currency.js +1 -1
  360. package/src/sap/ui/model/type/Date.js +1 -2
  361. package/src/sap/ui/model/type/DateInterval.js +5 -5
  362. package/src/sap/ui/model/type/DateTime.js +1 -1
  363. package/src/sap/ui/model/type/DateTimeInterval.js +1 -1
  364. package/src/sap/ui/model/type/FileSize.js +1 -1
  365. package/src/sap/ui/model/type/Float.js +1 -1
  366. package/src/sap/ui/model/type/Integer.js +1 -1
  367. package/src/sap/ui/model/type/String.js +1 -1
  368. package/src/sap/ui/model/type/Time.js +1 -1
  369. package/src/sap/ui/model/type/TimeInterval.js +1 -1
  370. package/src/sap/ui/model/type/Unit.js +1 -1
  371. package/src/sap/ui/model/xml/XMLModel.js +2 -2
  372. package/src/sap/ui/model/xml/XMLPropertyBinding.js +4 -2
  373. package/src/sap/ui/performance/BeaconRequest.js +8 -10
  374. package/src/sap/ui/performance/trace/Interaction.js +11 -2
  375. package/src/sap/ui/qunit/qunit-coverage-istanbul.js +60 -6
  376. package/src/sap/ui/qunit/utils/ControlIterator.js +1 -1
  377. package/src/sap/ui/qunit/utils/MemoryLeakCheck.js +10 -11
  378. package/src/sap/ui/qunit/utils/nextUIUpdate.js +51 -0
  379. package/src/sap/ui/qunit/utils/waitForThemeApplied.js +16 -14
  380. package/src/sap/ui/test/BlanketReporterUI.view.xml +5 -2
  381. package/src/sap/ui/test/ModuleTracking.js +326 -0
  382. package/src/sap/ui/test/OpaPlugin.js +3 -3
  383. package/src/sap/ui/test/TestUtils.js +8 -7
  384. package/src/sap/ui/test/autowaiter/_UIUpdatesWaiter.js +3 -2
  385. package/src/sap/ui/test/generic/TestBase.js +1 -1
  386. package/src/sap/ui/test/matchers/Descendant.js +1 -1
  387. package/src/sap/ui/test/matchers/Sibling.js +1 -1
  388. package/src/sap/ui/test/selectors/_ControlSelectorGenerator.js +2 -0
  389. package/src/sap/ui/test/selectors/_DropdownItem.js +1 -0
  390. package/src/sap/ui/test/selectors/_LabelFor.js +3 -2
  391. package/src/sap/ui/test/selectors/_TableRowItem.js +1 -0
  392. package/src/sap/ui/test/starter/_setupAndStart.js +35 -11
  393. package/src/sap/ui/util/Storage.js +1 -1
  394. package/src/ui5loader-autoconfig.js +14 -10
  395. package/test/sap/ui/core/ComponentCleanup.html +228 -225
  396. package/test/sap/ui/core/ComponentConfig.html +1 -1
  397. package/test/sap/ui/core/ComponentExtensibility_CustomizingDisabled.html +1 -1
  398. package/test/sap/ui/core/ComponentExtensibility_legacyAPIs.html +1 -1
  399. package/test/sap/ui/core/ComponentSimple.html +1 -1
  400. package/test/sap/ui/core/ComponentSimpleModel.html +1 -1
  401. package/test/sap/ui/core/ComponentSupport.html +1 -1
  402. package/test/sap/ui/core/DateFormat.js +3 -3
  403. package/test/sap/ui/core/EventBroadcaster.html +62 -62
  404. package/test/sap/ui/core/Formats.html +4 -2
  405. package/test/sap/ui/core/GenericEventBinding.html +53 -52
  406. package/test/sap/ui/core/HTMLControl.html +94 -93
  407. package/test/sap/ui/core/HyphenationPlayground.html +10 -9
  408. package/test/sap/ui/core/ListFormat.js +3 -3
  409. package/test/sap/ui/core/NumberFormat.js +3 -3
  410. package/test/sap/ui/core/ODataAnnotationsPerformance.html +28 -28
  411. package/test/sap/ui/core/ODataV2CanonicalRequests.html +3 -2
  412. package/test/sap/ui/core/ODataV2Messages.html +4 -3
  413. package/test/sap/ui/core/PopupWithUserSelection.html +1 -1
  414. package/test/sap/ui/core/Strings.js +3 -3
  415. package/test/sap/ui/core/Strings.view.xml +5 -1
  416. package/test/sap/ui/core/ThemeParameters.html +31 -30
  417. package/test/sap/ui/core/ValidateURL.html +143 -143
  418. package/test/sap/ui/core/demokit/sample/BusyIndicator/manifest.json +2 -1
  419. package/test/sap/ui/core/demokit/sample/Commands/Commands.html +1 -1
  420. package/test/sap/ui/core/demokit/sample/Commands/manifest.json +2 -2
  421. package/test/sap/ui/core/demokit/sample/ControlBusyIndicator/manifest.json +2 -1
  422. package/test/sap/ui/core/demokit/sample/ControllerExtension/manifest.json +1 -0
  423. package/test/sap/ui/core/demokit/sample/FieldGroup/manifest.json +1 -0
  424. package/test/sap/ui/core/demokit/sample/Html/manifest.json +1 -0
  425. package/test/sap/ui/core/demokit/sample/Html/preserveDOM/manifest.json +1 -0
  426. package/test/sap/ui/core/demokit/sample/Html/static/manifest.json +1 -0
  427. package/test/sap/ui/core/demokit/sample/HyphenationAPI/C.controller.js +3 -3
  428. package/test/sap/ui/core/demokit/sample/Icon/manifest.json +2 -1
  429. package/test/sap/ui/core/demokit/sample/InvisibleMessage/InvisibleMessage.controller.js +4 -4
  430. package/test/sap/ui/core/demokit/sample/InvisibleMessage/manifest.json +2 -1
  431. package/test/sap/ui/core/demokit/sample/InvisibleText/manifest.json +2 -1
  432. package/test/sap/ui/core/demokit/sample/MessageManager/BasicMessages/Controller.controller.js +10 -10
  433. package/test/sap/ui/core/demokit/sample/MessageManager/BasicODataMessages/Controller.controller.js +7 -7
  434. package/test/sap/ui/core/demokit/sample/MessageManager/BasicODataMessages/manifest.json +1 -0
  435. package/test/sap/ui/core/demokit/sample/MessageManager/ODataBackendMessagesComp/webapp/Component.js +3 -2
  436. package/test/sap/ui/core/demokit/sample/MessageManager/ODataBackendMessagesComp/webapp/controller/Employee.controller.js +3 -2
  437. package/test/sap/ui/core/demokit/sample/MessageManager/ODataBackendMessagesComp/webapp/index.html +7 -8
  438. package/test/sap/ui/core/demokit/sample/OpaAction/manifest.json +1 -0
  439. package/test/sap/ui/core/demokit/sample/OpaAutoWaitParams/OpaAutoWaitParams.js +1 -1
  440. package/test/sap/ui/core/demokit/sample/OpaAutoWaitParams/applicationUnderTest/manifest.json +2 -2
  441. package/test/sap/ui/core/demokit/sample/OpaAutoWaitParams/manifest.json +2 -1
  442. package/test/sap/ui/core/demokit/sample/OpaBusyIndicator/applicationUnderTest/manifest.json +2 -2
  443. package/test/sap/ui/core/demokit/sample/OpaBusyIndicator/manifest.json +2 -1
  444. package/test/sap/ui/core/demokit/sample/OpaById/applicationUnderTest/manifest.json +2 -2
  445. package/test/sap/ui/core/demokit/sample/OpaById/manifest.json +2 -1
  446. package/test/sap/ui/core/demokit/sample/OpaDynamicWait/applicationUnderTest/manifest.json +2 -2
  447. package/test/sap/ui/core/demokit/sample/OpaDynamicWait/manifest.json +2 -1
  448. package/test/sap/ui/core/demokit/sample/OpaGetStarted/applicationUnderTest/index.html +9 -6
  449. package/test/sap/ui/core/demokit/sample/OpaGetStarted/manifest.json +2 -1
  450. package/test/sap/ui/core/demokit/sample/OpaMatchers/applicationUnderTest/manifest.json +2 -2
  451. package/test/sap/ui/core/demokit/sample/OpaMatchers/manifest.json +2 -1
  452. package/test/sap/ui/core/demokit/sample/OpaPageObject/applicationUnderTest/manifest.json +2 -2
  453. package/test/sap/ui/core/demokit/sample/OpaPageObject/manifest.json +2 -1
  454. package/test/sap/ui/core/demokit/sample/OpaStartup/iStartMyAppInAFrame/applicationUnderTest/manifest.json +2 -2
  455. package/test/sap/ui/core/demokit/sample/OpaStartup/iStartMyAppInAFrame/manifest.json +2 -1
  456. package/test/sap/ui/core/demokit/sample/OpaStartup/iStartMyUIComponent/applicationUnderTest/manifest.json +2 -2
  457. package/test/sap/ui/core/demokit/sample/OpaStartup/iStartMyUIComponent/manifest.json +2 -1
  458. package/test/sap/ui/core/demokit/sample/OpaStaticAreaControls/applicationUnderTest/manifest.json +2 -2
  459. package/test/sap/ui/core/demokit/sample/OpaStaticAreaControls/manifest.json +2 -1
  460. package/test/sap/ui/core/demokit/sample/OpaTestLibrary/applicationUnderTest/manifest.json +2 -2
  461. package/test/sap/ui/core/demokit/sample/OpaTestLibrary/manifest.json +2 -1
  462. package/test/sap/ui/core/demokit/sample/OpaURLParameters/iStartMyAppInAFrameWithURLParameters/applicationUnderTest/manifest.json +2 -2
  463. package/test/sap/ui/core/demokit/sample/OpaURLParameters/iStartMyAppInAFrameWithURLParameters/manifest.json +2 -1
  464. package/test/sap/ui/core/demokit/sample/OpaURLParameters/iStartMyUIComponentWithURLParameters/applicationUnderTest/manifest.json +2 -2
  465. package/test/sap/ui/core/demokit/sample/OpaURLParameters/iStartMyUIComponentWithURLParameters/manifest.json +2 -1
  466. package/test/sap/ui/core/demokit/sample/OpaWithSupportAssistant/applicationUnderTest/index.html +13 -10
  467. package/test/sap/ui/core/demokit/sample/OpaWithSupportAssistant/manifest.json +2 -1
  468. package/test/sap/ui/core/demokit/sample/PatternMatching/Patterns.html +11 -8
  469. package/test/sap/ui/core/demokit/sample/PatternMatching/manifest.json +2 -1
  470. package/test/sap/ui/core/demokit/sample/PatternMatching/patternApp/manifest.json +2 -2
  471. package/test/sap/ui/core/demokit/sample/RoutingFullscreen/RoutingFullscreen.html +11 -8
  472. package/test/sap/ui/core/demokit/sample/RoutingFullscreen/manifest.json +2 -1
  473. package/test/sap/ui/core/demokit/sample/RoutingMasterDetail/RoutingMasterDetail.html +11 -8
  474. package/test/sap/ui/core/demokit/sample/RoutingMasterDetail/manifest.json +2 -1
  475. package/test/sap/ui/core/demokit/sample/RoutingNestedComponent/RoutingNestedComponent.html +1 -1
  476. package/test/sap/ui/core/demokit/sample/RoutingNestedComponent/manifest.json +2 -2
  477. package/test/sap/ui/core/demokit/sample/RoutingNestedComponent/reuse/categories/manifest.json +2 -1
  478. package/test/sap/ui/core/demokit/sample/RoutingNestedComponent/reuse/products/manifest.json +2 -1
  479. package/test/sap/ui/core/demokit/sample/RoutingNestedComponent/reuse/suppliers/manifest.json +2 -1
  480. package/test/sap/ui/core/demokit/sample/RoutingNestedComponent/test/integration/opaTests.qunit.html +1 -1
  481. package/test/sap/ui/core/demokit/sample/RoutingNestedComponent/test/integration/opaTests.qunit.js +5 -4
  482. package/test/sap/ui/core/demokit/sample/TargetsStandalone/TargetsStandalone.html +11 -8
  483. package/test/sap/ui/core/demokit/sample/TargetsStandalone/manifest.json +2 -1
  484. package/test/sap/ui/core/demokit/sample/ThemeCustomClasses/ThemeCustomClasses.controller.js +3 -3
  485. package/test/sap/ui/core/demokit/sample/ThemeCustomClasses/manifest.json +1 -0
  486. package/test/sap/ui/core/demokit/sample/TypeCurrency/manifest.json +1 -0
  487. package/test/sap/ui/core/demokit/sample/TypeDateAsDate/manifest.json +1 -0
  488. package/test/sap/ui/core/demokit/sample/TypeDateAsString/manifest.json +1 -0
  489. package/test/sap/ui/core/demokit/sample/TypeDateTime/manifest.json +1 -0
  490. package/test/sap/ui/core/demokit/sample/TypeFileSize/manifest.json +1 -0
  491. package/test/sap/ui/core/demokit/sample/TypeFloat/manifest.json +1 -0
  492. package/test/sap/ui/core/demokit/sample/TypeInteger/manifest.json +1 -0
  493. package/test/sap/ui/core/demokit/sample/TypeTimeAsTime/manifest.json +1 -0
  494. package/test/sap/ui/core/demokit/sample/View/async/manifest.json +2 -1
  495. package/test/sap/ui/core/demokit/sample/View/preprocessor/manifest.json +2 -1
  496. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/Opa.qunit.js +9 -8
  497. package/test/sap/ui/core/demokit/sample/ViewTemplate/scenario/manifest.json +2 -1
  498. package/test/sap/ui/core/demokit/sample/ViewTemplate/types/Opa.qunit.js +12 -11
  499. package/test/sap/ui/core/demokit/sample/XMLComposite/02/manifest.json +1 -0
  500. package/test/sap/ui/core/demokit/sample/common/Controller.js +8 -8
  501. package/test/sap/ui/core/demokit/sample/common/Helper.js +19 -2
  502. package/test/sap/ui/core/demokit/sample/common/init.js +25 -21
  503. package/test/sap/ui/core/demokit/sample/common/pages/Any.js +3 -0
  504. package/test/sap/ui/core/demokit/sample/gherkin/GherkinWithOPA5/WebsiteCode.js +8 -7
  505. package/test/sap/ui/core/demokit/sample/gherkin/GherkinWithPageObjects/applicationUnderTest/manifest.json +1 -0
  506. package/test/sap/ui/core/demokit/sample/gherkin/GherkinWithPageObjects/manifest.json +2 -1
  507. package/test/sap/ui/core/demokit/sample/matcher/BindingPath/manifest.json +2 -1
  508. package/test/sap/ui/core/demokit/sample/matcher/BindingPath/webapp/manifest.json +2 -2
  509. package/test/sap/ui/core/demokit/sample/matcher/Descendant/manifest.json +2 -1
  510. package/test/sap/ui/core/demokit/sample/matcher/Descendant/webapp/manifest.json +2 -2
  511. package/test/sap/ui/core/demokit/sample/matcher/I18NText/manifest.json +2 -1
  512. package/test/sap/ui/core/demokit/sample/matcher/I18NText/webapp/manifest.json +2 -2
  513. package/test/sap/ui/core/demokit/sample/matcher/LabelFor/manifest.json +2 -1
  514. package/test/sap/ui/core/demokit/sample/matcher/LabelFor/webapp/manifest.json +2 -2
  515. package/test/sap/ui/core/demokit/sample/odata/types/v2/DateTimeOffset/manifest.json +1 -0
  516. package/test/sap/ui/core/demokit/sample/odata/types/v4/Date/manifest.json +1 -0
  517. package/test/sap/ui/core/demokit/sample/odata/types/v4/TimeOfDay/manifest.json +1 -0
  518. package/test/sap/ui/core/demokit/sample/odata/v2/AutoExpand/AutoExpand.view.xml +6 -2
  519. package/test/sap/ui/core/demokit/sample/odata/v4/Ancestry/Main.view.xml +7 -3
  520. package/test/sap/ui/core/demokit/sample/odata/v4/DataAggregation/DataAggregation.controller.js +2 -2
  521. package/test/sap/ui/core/demokit/sample/odata/v4/DataAggregation/DataAggregation.view.xml +7 -4
  522. package/test/sap/ui/core/demokit/sample/odata/v4/DataAggregation/Opa.qunit.js +9 -8
  523. package/test/sap/ui/core/demokit/sample/odata/v4/DataAggregation/tests/expandPageCollapse.js +1 -1
  524. package/test/sap/ui/core/demokit/sample/odata/v4/DataAggregation/tests/filter.js +1 -1
  525. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/ObjectPage.controller.js +3 -2
  526. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/Opa.qunit.js +13 -11
  527. package/test/sap/ui/core/demokit/sample/odata/v4/Draft/ListReport.controller.js +3 -2
  528. package/test/sap/ui/core/demokit/sample/odata/v4/Draft/Opa.qunit.js +13 -14
  529. package/test/sap/ui/core/demokit/sample/odata/v4/FieldGroups/Opa.qunit.js +14 -11
  530. package/test/sap/ui/core/demokit/sample/odata/v4/FlatDataAggregation/Component.js +4 -4
  531. package/test/sap/ui/core/demokit/sample/odata/v4/FlatDataAggregation/FlatDataAggregation.controller.js +6 -4
  532. package/test/sap/ui/core/demokit/sample/odata/v4/FlatDataAggregation/FlatDataAggregation.view.xml +6 -2
  533. package/test/sap/ui/core/demokit/sample/odata/v4/FlexibleColumnLayout/Main.controller.js +3 -3
  534. package/test/sap/ui/core/demokit/sample/odata/v4/FlexibleColumnLayout/Opa.qunit.js +19 -25
  535. package/test/sap/ui/core/demokit/sample/odata/v4/GridTable/GridTable.view.xml +6 -2
  536. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/Component.js +19 -0
  537. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/Main.controller.js +93 -0
  538. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/Main.view.xml +89 -0
  539. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/SandboxModel.js +10 -0
  540. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/data/all.json +396 -0
  541. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/data/metadata.xml +423 -0
  542. package/test/sap/ui/core/demokit/sample/odata/v4/HierarchyBindAction/manifest.json +70 -0
  543. package/test/sap/ui/core/demokit/sample/odata/v4/LateProperties/Opa.OptimisticBatch.qunit.js +11 -10
  544. package/test/sap/ui/core/demokit/sample/odata/v4/LateProperties/Opa.qunit.js +10 -9
  545. package/test/sap/ui/core/demokit/sample/odata/v4/ListBinding/Opa.qunit.js +11 -10
  546. package/test/sap/ui/core/demokit/sample/odata/v4/ListBindingTemplate/Opa.qunit.js +8 -7
  547. package/test/sap/ui/core/demokit/sample/odata/v4/MultipleInlineCreationRowsGrid/Main.controller.js +8 -10
  548. package/test/sap/ui/core/demokit/sample/odata/v4/MultipleInlineCreationRowsGrid/Main.view.xml +5 -2
  549. package/test/sap/ui/core/demokit/sample/odata/v4/MultipleInlineCreationRowsGrid/Opa.qunit.js +16 -13
  550. package/test/sap/ui/core/demokit/sample/odata/v4/Products/Main.controller.js +3 -2
  551. package/test/sap/ui/core/demokit/sample/odata/v4/Products/Opa.qunit.js +12 -11
  552. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/MIT.RecursiveHierarchy maintenance.html +408 -0
  553. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/Opa.qunit.js +26 -8
  554. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/RecursiveHierarchy.controller.js +78 -13
  555. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/RecursiveHierarchy.view.xml +48 -9
  556. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/SandboxModel.js +379 -287
  557. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/pages/Main.js +38 -5
  558. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/tests/createEdit.js +128 -0
  559. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/tests/pageExpandCollapse.js +24 -23
  560. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrderTP100_V2/Opa.qunit.js +11 -10
  561. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrderTP100_V4/Opa.qunit.js +10 -9
  562. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/Component.js +3 -2
  563. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/Opa.qunit.js +15 -14
  564. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/pages/Main.js +9 -8
  565. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/tests/ChangeContext.js +1 -1
  566. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/tests/Create.js +1 -1
  567. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/tests/CreateMultiple.js +1 -1
  568. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/tests/CreateRelative.js +1 -1
  569. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/tests/MessageHandling.js +1 -1
  570. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/tests/TypeDeterminationAndDelete.js +8 -9
  571. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/tests/WriteNonDeferredGroup.js +1 -1
  572. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/tests/additionalTargets.js +1 -1
  573. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrdersRTATest/Opa.qunit.js +9 -8
  574. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrdersRTATest/tests/AdaptSalesOrdersTable.js +1 -1
  575. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrdersTemplate/Opa.qunit.js +10 -9
  576. package/test/sap/ui/core/demokit/sample/odata/v4/ServerDrivenPaging/Main.view.xml +5 -2
  577. package/test/sap/ui/core/demokit/sample/odata/v4/ServerDrivenPaging/Opa.qunit.js +10 -9
  578. package/test/sap/ui/core/demokit/sample/odata/v4/ServerDrivenPaging/pages/Main.js +4 -2
  579. package/test/sap/ui/core/demokit/sample/odata/v4/Sticky/Opa.qunit.js +11 -10
  580. package/test/sap/ui/core/demokit/tutorial/databinding/01/package.json +2 -5
  581. package/test/sap/ui/core/demokit/tutorial/databinding/01/ui5.yaml +8 -0
  582. package/test/sap/ui/core/demokit/tutorial/databinding/01/webapp/index.js +7 -3
  583. package/test/sap/ui/core/demokit/tutorial/databinding/02/package.json +2 -5
  584. package/test/sap/ui/core/demokit/tutorial/databinding/02/ui5.yaml +8 -0
  585. package/test/sap/ui/core/demokit/tutorial/databinding/02/webapp/index.js +4 -3
  586. package/test/sap/ui/core/demokit/tutorial/databinding/03/package.json +2 -5
  587. package/test/sap/ui/core/demokit/tutorial/databinding/03/ui5.yaml +8 -0
  588. package/test/sap/ui/core/demokit/tutorial/databinding/03/webapp/index.js +4 -3
  589. package/test/sap/ui/core/demokit/tutorial/databinding/04/package.json +2 -5
  590. package/test/sap/ui/core/demokit/tutorial/databinding/04/ui5.yaml +8 -0
  591. package/test/sap/ui/core/demokit/tutorial/databinding/04/webapp/index.js +4 -3
  592. package/test/sap/ui/core/demokit/tutorial/databinding/05/package.json +2 -5
  593. package/test/sap/ui/core/demokit/tutorial/databinding/05/ui5.yaml +8 -0
  594. package/test/sap/ui/core/demokit/tutorial/databinding/05/webapp/index.js +4 -3
  595. package/test/sap/ui/core/demokit/tutorial/databinding/06/package.json +2 -5
  596. package/test/sap/ui/core/demokit/tutorial/databinding/06/ui5.yaml +8 -0
  597. package/test/sap/ui/core/demokit/tutorial/databinding/06/webapp/index.js +4 -3
  598. package/test/sap/ui/core/demokit/tutorial/databinding/07/package.json +2 -5
  599. package/test/sap/ui/core/demokit/tutorial/databinding/07/ui5.yaml +8 -0
  600. package/test/sap/ui/core/demokit/tutorial/databinding/07/webapp/index.js +4 -3
  601. package/test/sap/ui/core/demokit/tutorial/databinding/08/package.json +2 -5
  602. package/test/sap/ui/core/demokit/tutorial/databinding/08/ui5.yaml +8 -0
  603. package/test/sap/ui/core/demokit/tutorial/databinding/08/webapp/index.js +4 -3
  604. package/test/sap/ui/core/demokit/tutorial/databinding/09/package.json +2 -5
  605. package/test/sap/ui/core/demokit/tutorial/databinding/09/ui5.yaml +8 -0
  606. package/test/sap/ui/core/demokit/tutorial/databinding/09/webapp/index.js +4 -3
  607. package/test/sap/ui/core/demokit/tutorial/databinding/10/package.json +2 -5
  608. package/test/sap/ui/core/demokit/tutorial/databinding/10/ui5.yaml +8 -0
  609. package/test/sap/ui/core/demokit/tutorial/databinding/10/webapp/index.js +4 -3
  610. package/test/sap/ui/core/demokit/tutorial/databinding/11/package.json +2 -5
  611. package/test/sap/ui/core/demokit/tutorial/databinding/11/ui5.yaml +8 -0
  612. package/test/sap/ui/core/demokit/tutorial/databinding/11/webapp/index.js +6 -4
  613. package/test/sap/ui/core/demokit/tutorial/databinding/12/package.json +2 -5
  614. package/test/sap/ui/core/demokit/tutorial/databinding/12/ui5.yaml +8 -0
  615. package/test/sap/ui/core/demokit/tutorial/databinding/12/webapp/index.js +6 -4
  616. package/test/sap/ui/core/demokit/tutorial/databinding/13/package.json +2 -5
  617. package/test/sap/ui/core/demokit/tutorial/databinding/13/ui5.yaml +8 -0
  618. package/test/sap/ui/core/demokit/tutorial/databinding/13/webapp/index.js +6 -4
  619. package/test/sap/ui/core/demokit/tutorial/databinding/14/package.json +2 -5
  620. package/test/sap/ui/core/demokit/tutorial/databinding/14/ui5.yaml +8 -0
  621. package/test/sap/ui/core/demokit/tutorial/databinding/14/webapp/index.js +6 -4
  622. package/test/sap/ui/core/demokit/tutorial/databinding/15/package.json +2 -5
  623. package/test/sap/ui/core/demokit/tutorial/databinding/15/ui5.yaml +8 -0
  624. package/test/sap/ui/core/demokit/tutorial/databinding/15/webapp/index.js +6 -4
  625. package/test/sap/ui/core/demokit/tutorial/mockserver/01/package.json +2 -5
  626. package/test/sap/ui/core/demokit/tutorial/mockserver/01/ui5.yaml +8 -0
  627. package/test/sap/ui/core/demokit/tutorial/mockserver/01/webapp/manifest.json +1 -1
  628. package/test/sap/ui/core/demokit/tutorial/mockserver/02/package.json +2 -5
  629. package/test/sap/ui/core/demokit/tutorial/mockserver/02/ui5.yaml +8 -0
  630. package/test/sap/ui/core/demokit/tutorial/mockserver/02/webapp/manifest.json +1 -1
  631. package/test/sap/ui/core/demokit/tutorial/mockserver/03/package.json +2 -5
  632. package/test/sap/ui/core/demokit/tutorial/mockserver/03/ui5.yaml +8 -0
  633. package/test/sap/ui/core/demokit/tutorial/mockserver/03/webapp/manifest.json +1 -1
  634. package/test/sap/ui/core/demokit/tutorial/mockserver/04/package.json +2 -5
  635. package/test/sap/ui/core/demokit/tutorial/mockserver/04/ui5.yaml +8 -0
  636. package/test/sap/ui/core/demokit/tutorial/mockserver/04/webapp/manifest.json +1 -1
  637. package/test/sap/ui/core/demokit/tutorial/navigation/01/package.json +2 -4
  638. package/test/sap/ui/core/demokit/tutorial/navigation/01/ui5.yaml +7 -0
  639. package/test/sap/ui/core/demokit/tutorial/navigation/01/webapp/index.html +1 -1
  640. package/test/sap/ui/core/demokit/tutorial/navigation/02/package.json +2 -4
  641. package/test/sap/ui/core/demokit/tutorial/navigation/02/ui5.yaml +7 -0
  642. package/test/sap/ui/core/demokit/tutorial/navigation/02/webapp/index.html +1 -1
  643. package/test/sap/ui/core/demokit/tutorial/navigation/03/package.json +2 -4
  644. package/test/sap/ui/core/demokit/tutorial/navigation/03/ui5.yaml +7 -0
  645. package/test/sap/ui/core/demokit/tutorial/navigation/03/webapp/index.html +1 -1
  646. package/test/sap/ui/core/demokit/tutorial/navigation/04/package.json +2 -4
  647. package/test/sap/ui/core/demokit/tutorial/navigation/04/ui5.yaml +7 -0
  648. package/test/sap/ui/core/demokit/tutorial/navigation/04/webapp/index.html +1 -1
  649. package/test/sap/ui/core/demokit/tutorial/navigation/05/package.json +2 -4
  650. package/test/sap/ui/core/demokit/tutorial/navigation/05/ui5.yaml +7 -0
  651. package/test/sap/ui/core/demokit/tutorial/navigation/05/webapp/index.html +1 -1
  652. package/test/sap/ui/core/demokit/tutorial/navigation/06/package.json +2 -4
  653. package/test/sap/ui/core/demokit/tutorial/navigation/06/ui5.yaml +7 -0
  654. package/test/sap/ui/core/demokit/tutorial/navigation/06/webapp/index.html +1 -1
  655. package/test/sap/ui/core/demokit/tutorial/navigation/07/package.json +2 -4
  656. package/test/sap/ui/core/demokit/tutorial/navigation/07/ui5.yaml +7 -0
  657. package/test/sap/ui/core/demokit/tutorial/navigation/07/webapp/index.html +1 -1
  658. package/test/sap/ui/core/demokit/tutorial/navigation/08/package.json +2 -4
  659. package/test/sap/ui/core/demokit/tutorial/navigation/08/ui5.yaml +7 -0
  660. package/test/sap/ui/core/demokit/tutorial/navigation/08/webapp/index.html +1 -1
  661. package/test/sap/ui/core/demokit/tutorial/navigation/09/package.json +2 -4
  662. package/test/sap/ui/core/demokit/tutorial/navigation/09/ui5.yaml +7 -0
  663. package/test/sap/ui/core/demokit/tutorial/navigation/09/webapp/index.html +1 -1
  664. package/test/sap/ui/core/demokit/tutorial/navigation/10/package.json +2 -4
  665. package/test/sap/ui/core/demokit/tutorial/navigation/10/ui5.yaml +7 -0
  666. package/test/sap/ui/core/demokit/tutorial/navigation/10/webapp/index.html +1 -1
  667. package/test/sap/ui/core/demokit/tutorial/navigation/11/package.json +2 -4
  668. package/test/sap/ui/core/demokit/tutorial/navigation/11/ui5.yaml +7 -0
  669. package/test/sap/ui/core/demokit/tutorial/navigation/11/webapp/index.html +1 -1
  670. package/test/sap/ui/core/demokit/tutorial/navigation/12/package.json +2 -4
  671. package/test/sap/ui/core/demokit/tutorial/navigation/12/ui5.yaml +7 -0
  672. package/test/sap/ui/core/demokit/tutorial/navigation/12/webapp/index.html +1 -1
  673. package/test/sap/ui/core/demokit/tutorial/navigation/13/package.json +2 -4
  674. package/test/sap/ui/core/demokit/tutorial/navigation/13/ui5.yaml +7 -0
  675. package/test/sap/ui/core/demokit/tutorial/navigation/13/webapp/index.html +1 -1
  676. package/test/sap/ui/core/demokit/tutorial/navigation/14/package.json +2 -4
  677. package/test/sap/ui/core/demokit/tutorial/navigation/14/ui5.yaml +7 -0
  678. package/test/sap/ui/core/demokit/tutorial/navigation/14/webapp/index.html +1 -1
  679. package/test/sap/ui/core/demokit/tutorial/navigation/15/package.json +2 -4
  680. package/test/sap/ui/core/demokit/tutorial/navigation/15/ui5.yaml +7 -0
  681. package/test/sap/ui/core/demokit/tutorial/navigation/15/webapp/index.html +1 -1
  682. package/test/sap/ui/core/demokit/tutorial/navigation/16/package.json +2 -4
  683. package/test/sap/ui/core/demokit/tutorial/navigation/16/ui5.yaml +7 -0
  684. package/test/sap/ui/core/demokit/tutorial/navigation/16/webapp/index.html +1 -1
  685. package/test/sap/ui/core/demokit/tutorial/navigation/17/package.json +4 -6
  686. package/test/sap/ui/core/demokit/tutorial/navigation/17/ui5.yaml +8 -1
  687. package/test/sap/ui/core/demokit/tutorial/navigation/17/webapp/index.html +1 -1
  688. package/test/sap/ui/core/demokit/tutorial/navigation/index.html +2 -2
  689. package/test/sap/ui/core/demokit/tutorial/odatav4/01/package.json +2 -6
  690. package/test/sap/ui/core/demokit/tutorial/odatav4/01/ui5.yaml +9 -0
  691. package/test/sap/ui/core/demokit/tutorial/odatav4/02/package.json +2 -6
  692. package/test/sap/ui/core/demokit/tutorial/odatav4/02/ui5.yaml +9 -0
  693. package/test/sap/ui/core/demokit/tutorial/odatav4/03/package.json +2 -6
  694. package/test/sap/ui/core/demokit/tutorial/odatav4/03/ui5.yaml +9 -0
  695. package/test/sap/ui/core/demokit/tutorial/odatav4/04/package.json +2 -6
  696. package/test/sap/ui/core/demokit/tutorial/odatav4/04/ui5.yaml +9 -0
  697. package/test/sap/ui/core/demokit/tutorial/odatav4/05/package.json +2 -6
  698. package/test/sap/ui/core/demokit/tutorial/odatav4/05/ui5.yaml +9 -0
  699. package/test/sap/ui/core/demokit/tutorial/odatav4/06/package.json +2 -6
  700. package/test/sap/ui/core/demokit/tutorial/odatav4/06/ui5.yaml +9 -0
  701. package/test/sap/ui/core/demokit/tutorial/odatav4/06/webapp/controller/App.controller.js +5 -5
  702. package/test/sap/ui/core/demokit/tutorial/odatav4/07/package.json +2 -6
  703. package/test/sap/ui/core/demokit/tutorial/odatav4/07/ui5.yaml +9 -0
  704. package/test/sap/ui/core/demokit/tutorial/odatav4/07/webapp/controller/App.controller.js +7 -7
  705. package/test/sap/ui/core/demokit/tutorial/odatav4/08/package.json +2 -6
  706. package/test/sap/ui/core/demokit/tutorial/odatav4/08/ui5.yaml +9 -0
  707. package/test/sap/ui/core/demokit/tutorial/odatav4/08/webapp/controller/App.controller.js +7 -7
  708. package/test/sap/ui/core/demokit/tutorial/odatav4/08/webapp/test/integration/opaTests.qunit.js +5 -5
  709. package/test/sap/ui/core/demokit/tutorial/odatav4/08/webapp/test/integration/pages/Tutorial.js +1 -1
  710. package/test/sap/ui/core/demokit/tutorial/odatav4/09/package.json +2 -6
  711. package/test/sap/ui/core/demokit/tutorial/odatav4/09/ui5.yaml +9 -0
  712. package/test/sap/ui/core/demokit/tutorial/odatav4/09/webapp/controller/App.controller.js +7 -7
  713. package/test/sap/ui/core/demokit/tutorial/odatav4/10/package.json +2 -6
  714. package/test/sap/ui/core/demokit/tutorial/odatav4/10/ui5.yaml +9 -0
  715. package/test/sap/ui/core/demokit/tutorial/odatav4/10/webapp/controller/App.controller.js +7 -7
  716. package/test/sap/ui/core/demokit/tutorial/odatav4/11/package.json +2 -6
  717. package/test/sap/ui/core/demokit/tutorial/odatav4/11/ui5.yaml +9 -0
  718. package/test/sap/ui/core/demokit/tutorial/odatav4/11/webapp/controller/App.controller.js +7 -7
  719. package/test/sap/ui/core/demokit/tutorial/odatav4/11/webapp/test/integration/opaTests.qunit.js +5 -5
  720. package/test/sap/ui/core/demokit/tutorial/odatav4/11/webapp/test/integration/pages/Tutorial.js +1 -1
  721. package/test/sap/ui/core/demokit/tutorial/troubleshooting/01/package.json +2 -5
  722. package/test/sap/ui/core/demokit/tutorial/troubleshooting/01/ui5.yaml +8 -0
  723. package/test/sap/ui/core/demokit/tutorial/troubleshooting/01/webapp/manifest.json +1 -1
  724. package/test/sap/ui/core/demokit/tutorial/troubleshooting/01/webapp/test/integration/opaTests.qunit.js +6 -6
  725. package/test/sap/ui/core/frameoptions/createcontent.js +7 -6
  726. package/test/sap/ui/core/internal/samples/client/MusicCollection/index.html +1 -1
  727. package/test/sap/ui/core/internal/samples/composite/xmlcomposite/exStringAndFloat/Test.controller.js +3 -2
  728. package/test/sap/ui/core/internal/samples/composite/xmlcomposite/exTableWrapperOuterBinding/Test.controller.js +3 -2
  729. package/test/sap/ui/core/internal/samples/odata/twoFields/Opa.qunit.html +1 -1
  730. package/test/sap/ui/core/internal/samples/odata/twoFields/Opa.qunit.js +8 -8
  731. package/test/sap/ui/core/internal/samples/odata/twoFields/index.html +1 -1
  732. package/test/sap/ui/core/internal/samples/odata/v2/Products/Opa.qunit.html +1 -1
  733. package/test/sap/ui/core/internal/samples/odata/v2/Products/Opa.qunit.js +7 -7
  734. package/test/sap/ui/core/internal/samples/odata/v2/Products/index.html +1 -1
  735. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/Component.js +3 -2
  736. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/MIT.SalesOrders(V2).ODLB.create.html +2 -0
  737. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/Main.controller.js +4 -4
  738. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/Main.view.xml +6 -3
  739. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/Opa.qunit.html +1 -1
  740. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/Opa.qunit.js +9 -6
  741. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/SandboxModel.js +3 -0
  742. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/data/ODLB.create/TC3/SalesOrderSet_desc_4-1.json +16 -0
  743. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/index.html +1 -1
  744. package/test/sap/ui/core/internal/samples/odata/v2/SalesOrders/tests/ODataListBinding.create/TC3_SalesOrders_InlineCreationRow.js +9 -0
  745. package/test/sap/ui/core/internal/samples/odata/v2/TreeTable/Component.js +3 -2
  746. package/test/sap/ui/core/internal/samples/odata/v2/TreeTable/Main.controller.js +3 -3
  747. package/test/sap/ui/core/internal/samples/odata/v2/TreeTable/Main.view.xml +1 -1
  748. package/test/sap/ui/core/internal/samples/odata/v2/TreeTable/index.html +1 -1
  749. package/test/sap/ui/core/qunit/BlockLayerUtils.qunit.js +9 -7
  750. package/test/sap/ui/core/qunit/CalculatedFields.qunit.js +4 -2
  751. package/test/sap/ui/core/qunit/ContextMenuSupport.qunit.js +3 -2
  752. package/test/sap/ui/core/qunit/ControlDefinition.qunit.js +49 -28
  753. package/test/sap/ui/core/qunit/ControlRenderer.qunit.js +218 -223
  754. package/test/sap/ui/core/qunit/Core.qunit.js +39 -34
  755. package/test/sap/ui/core/qunit/CoreEvents.qunit.js +17 -15
  756. package/test/sap/ui/core/qunit/Core_libraryTerminologies_integration.qunit.js +12 -11
  757. package/test/sap/ui/core/qunit/Core_repeatedExecution.qunit.js +3 -3
  758. package/test/sap/ui/core/qunit/CustomStyleClassSupport.qunit.js +122 -119
  759. package/test/sap/ui/core/qunit/CustomThemeFallback.qunit.js +5 -17
  760. package/test/sap/ui/core/qunit/Declarative.qunit.js +37 -37
  761. package/test/sap/ui/core/qunit/Element_base.qunit.js +1 -1
  762. package/test/sap/ui/core/qunit/Element_data.qunit.js +5 -5
  763. package/test/sap/ui/core/qunit/Element_destroy.qunit.js +6 -4
  764. package/test/sap/ui/core/qunit/Element_focus.qunit.js +25 -24
  765. package/test/sap/ui/core/qunit/Element_metadata_selector.qunit.js +3 -2
  766. package/test/sap/ui/core/qunit/EnabledPropagator.qunit.js +7 -6
  767. package/test/sap/ui/core/qunit/EventBus.qunit.js +4 -3
  768. package/test/sap/ui/core/qunit/ExpressionParser.qunit.js +1 -1
  769. package/test/sap/ui/core/qunit/FastNavigation.qunit.js +3 -2
  770. package/test/sap/ui/core/qunit/FastNavigationWithWebComponents.qunit.js +5 -5
  771. package/test/sap/ui/core/qunit/FieldGroup.qunit.js +17 -13
  772. package/test/sap/ui/core/qunit/FocusHandler.qunit.js +11 -9
  773. package/test/sap/ui/core/qunit/Fragment.qunit.js +47 -46
  774. package/test/sap/ui/core/qunit/Fragment_legacyAPIs.qunit.js +63 -61
  775. package/test/sap/ui/core/qunit/HTML.qunit.js +67 -67
  776. package/test/sap/ui/core/qunit/Icon.qunit.js +66 -65
  777. package/test/sap/ui/core/qunit/IconPool.qunit.js +5 -4
  778. package/test/sap/ui/core/qunit/InvisibleText.qunit.js +17 -15
  779. package/test/sap/ui/core/qunit/Lib.qunit.js +8 -8
  780. package/test/sap/ui/core/qunit/LocalBusyIndicator.qunit.js +24 -24
  781. package/test/sap/ui/core/qunit/ManagedObject.qunit.js +3 -3
  782. package/test/sap/ui/core/qunit/PlaceAt.qunit.js +2 -2
  783. package/test/sap/ui/core/qunit/RenderManager.qunit.js +54 -53
  784. package/test/sap/ui/core/qunit/ResizeHandler.qunit.js +8 -9
  785. package/test/sap/ui/core/qunit/ScrollBar.qunit.js +7 -6
  786. package/test/sap/ui/core/qunit/ShortcutHints.qunit.js +13 -11
  787. package/test/sap/ui/core/qunit/StashedControlSupport.qunit.js +15 -14
  788. package/test/sap/ui/core/qunit/ThemeHelper.qunit.js +5 -4
  789. package/test/sap/ui/core/qunit/ThemeManager.qunit.js +47 -79
  790. package/test/sap/ui/core/qunit/ThemeParameters.qunit.js +44 -375
  791. package/test/sap/ui/core/qunit/ThemeParameters_legacyAPIs.qunit.js +686 -0
  792. package/test/sap/ui/core/qunit/Theming.qunit.js +88 -50
  793. package/test/sap/ui/core/qunit/Theming_default_and_fallback.qunit.js +130 -0
  794. package/test/sap/ui/core/qunit/TooltipBase.qunit.js +6 -4
  795. package/test/sap/ui/core/qunit/UIArea.qunit.js +258 -28
  796. package/test/sap/ui/core/qunit/analytics/testsuite4analytics.qunit.html +3 -3
  797. package/test/sap/ui/core/qunit/analytics/testsuite4analytics.qunit.js +9 -8
  798. package/test/sap/ui/core/qunit/app/MessageListBinding.qunit.js +10 -10
  799. package/test/sap/ui/core/qunit/base/Config.qunit.js +12 -2
  800. package/test/sap/ui/core/qunit/base/Config_cascade.qunit.js +123 -52
  801. package/test/sap/ui/core/qunit/base/Config_meta.qunit.html +2 -0
  802. package/test/sap/ui/core/qunit/base/config/GlobalConfig.js +3 -1
  803. package/test/sap/ui/core/qunit/base/config/GlobalConfigForCascade.js +4 -1
  804. package/test/sap/ui/core/qunit/base/i18n/Localization.qunit.js +4 -3
  805. package/test/sap/ui/core/qunit/base/i18n/ResourceBundle.qunit.js +13 -3
  806. package/test/sap/ui/core/qunit/base/util/UriParameters.qunit.js +27 -1
  807. package/test/sap/ui/core/qunit/bootstrap/BootstrapCustomBootTaskPreloadCss.qunit.js +4 -4
  808. package/test/sap/ui/core/qunit/bootstrap/BootstrapMinimal.qunit.js +3 -3
  809. package/test/sap/ui/core/qunit/bootstrap/BootstrapMinimal_legacyAPIs.qunit.js +13 -11
  810. package/test/sap/ui/core/qunit/bootstrap/BootstrapPreload.qunit.js +1 -1
  811. package/test/sap/ui/core/qunit/bootstrap/BootstrapWithCustomBootTask.beforeBootstrap.qunit.js +22 -21
  812. package/test/sap/ui/core/qunit/bootstrap/BootstrapWithCustomBootTask.qunit.js +4 -9
  813. package/test/sap/ui/core/qunit/bootstrap/BootstrapWithCustomScript_legacyAPIs.qunit.js +13 -11
  814. package/test/sap/ui/core/qunit/bootstrap/BootstrapWithNoJQuery_legacyAPIs.qunit.js +7 -5
  815. package/test/sap/ui/core/qunit/bootstrap/CalendarClassLoadingWithCustomBootTaskAndPreload.qunit.js +27 -14
  816. package/test/sap/ui/core/qunit/bootstrap/CfgDefaults.qunit.js +4 -2
  817. package/test/sap/ui/core/qunit/bootstrap/CfgFromConfigAttribute.qunit.js +4 -3
  818. package/test/sap/ui/core/qunit/bootstrap/CfgFromGlobalObject.qunit.js +4 -3
  819. package/test/sap/ui/core/qunit/bootstrap/CfgFromTagAttributes.qunit.js +5 -4
  820. package/test/sap/ui/core/qunit/bootstrap/Configuration.qunit.js +2 -198
  821. package/test/sap/ui/core/qunit/bootstrap/Configuration_language_via_URL.qunit.js +210 -0
  822. package/test/sap/ui/core/qunit/bootstrap/ThemeVersion.qunit.js +33 -30
  823. package/test/sap/ui/core/qunit/bootstrap/testsuite.bootstrap.qunit.js +18 -6
  824. package/test/sap/ui/core/qunit/component/Component.qunit.js +26 -15
  825. package/test/sap/ui/core/qunit/component/ComponentSupport.qunit.js +6 -5
  826. package/test/sap/ui/core/qunit/component/Component_dependencyLoading.qunit.js +15 -9
  827. package/test/sap/ui/core/qunit/component/Component_dependencyLoading_unavoidablySync.qunit.js +10 -6
  828. package/test/sap/ui/core/qunit/component/Component_unavoidablySync.qunit.js +4 -3
  829. package/test/sap/ui/core/qunit/component/Customizing.qunit.js +11 -11
  830. package/test/sap/ui/core/qunit/component/Customizing_async.qunit.js +4 -3
  831. package/test/sap/ui/core/qunit/component/Customizing_disabled.qunit.js +9 -10
  832. package/test/sap/ui/core/qunit/component/Customizing_legacyAPIs.qunit.js +10 -11
  833. package/test/sap/ui/core/qunit/component/Customizing_multi.qunit.js +9 -11
  834. package/test/sap/ui/core/qunit/component/Customizing_unavoidablySync.qunit.js +9 -11
  835. package/test/sap/ui/core/qunit/component/ExtensionPoint.qunit.js +4 -5
  836. package/test/sap/ui/core/qunit/component/ExtensionPoint_unavoidablySync.qunit.js +4 -3
  837. package/test/sap/ui/core/qunit/component/Metadata.qunit.js +3 -3
  838. package/test/sap/ui/core/qunit/component/Models.qunit.js +103 -44
  839. package/test/sap/ui/core/qunit/component/UIComponent.qunit.js +38 -22
  840. package/test/sap/ui/core/qunit/component/UIComponent_unavoidablySync.qunit.js +23 -22
  841. package/test/sap/ui/core/qunit/component/testdata/dependencyLoading/component1/manifest.json +2 -1
  842. package/test/sap/ui/core/qunit/component/testdata/dependencyLoading/component2/manifest.json +1 -0
  843. package/test/sap/ui/core/qunit/component/testdata/dependencyLoading/component3/manifest.json +2 -1
  844. package/test/sap/ui/core/qunit/component/testdata/dependencyLoading/component4/manifest.json +1 -0
  845. package/test/sap/ui/core/qunit/component/testdata/dependencyLoading/component5/manifest.json +1 -1
  846. package/test/sap/ui/core/qunit/component/testdata/dependencyLoading/component6/manifest.json +1 -0
  847. package/test/sap/ui/core/qunit/component/testdata/dependencyLoading/componentVariant/manifest.json +1 -0
  848. package/test/sap/ui/core/qunit/component/testdata/v2asyncRootView/manifest.json +1 -1
  849. package/test/sap/ui/core/qunit/component/testdata/v2inline/Component.js +1 -1
  850. package/test/sap/ui/core/qunit/composite/XMLComposite.qunit.js +48 -48
  851. package/test/sap/ui/core/qunit/csp/ContentSecurityPolicy.qunit.js +18 -13
  852. package/test/sap/ui/core/qunit/dnd/DragAndDrop.qunit.js +19 -18
  853. package/test/sap/ui/core/qunit/dnd/DragInfo.qunit.js +13 -12
  854. package/test/sap/ui/core/qunit/dnd/DropInfo.qunit.js +5 -4
  855. package/test/sap/ui/core/qunit/generic/ControlMemoryLeaks.qunit.js +7 -6
  856. package/test/sap/ui/core/qunit/generic/DuplicateIdCheck.qunit.js +7 -6
  857. package/test/sap/ui/core/qunit/generic/legacy/ControlIterator.qunit.js +6 -6
  858. package/test/sap/ui/core/qunit/generic/legacy/ControlMemoryLeaks.qunit.js +20 -17
  859. package/test/sap/ui/core/qunit/generic/legacy/DuplicateIdCheck.qunit.js +8 -7
  860. package/test/sap/ui/core/qunit/i18n/LocaleData.qunit.js +1 -2
  861. package/test/sap/ui/core/qunit/internal/1Ring.qunit.html +14 -19
  862. package/test/sap/ui/core/qunit/internal/1Ring.qunit.js +34 -22
  863. package/test/sap/ui/core/qunit/internal/1RingModels.qunit.html +4 -5
  864. package/test/sap/ui/core/qunit/internal/1RingModels.qunit.js +1 -0
  865. package/test/sap/ui/core/qunit/internal/AnnotationParser.qunit.html +4 -4
  866. package/test/sap/ui/core/qunit/internal/ODataV4.qunit.html +6 -6
  867. package/test/sap/ui/core/qunit/internal/testsuite.feature-odata-v4.qunit.js +4 -0
  868. package/test/sap/ui/core/qunit/internal/testsuite.models.qunit.js +19 -9
  869. package/test/sap/ui/core/qunit/isBehindOtherElement.qunit.js +7 -7
  870. package/test/sap/ui/core/qunit/jquery-mobile-custom.qunit.js +3 -3
  871. package/test/sap/ui/core/qunit/jquery.sap.events.qunit.js +3 -2
  872. package/test/sap/ui/core/qunit/jquery.sap.global-config.qunit.js +2 -4
  873. package/test/sap/ui/core/qunit/jquery.sap.ui.qunit.js +20 -19
  874. package/test/sap/ui/core/qunit/json/JSONModel.qunit.js +5 -9
  875. package/test/sap/ui/core/qunit/messages/Messaging.qunit.js +137 -0
  876. package/test/sap/ui/core/qunit/messages/messagesDataBinding.qunit.js +3 -1
  877. package/test/sap/ui/core/qunit/messages/messagesEnd2End.qunit.js +10 -10
  878. package/test/sap/ui/core/qunit/messages/messagesGeneral.qunit.js +42 -46
  879. package/test/sap/ui/core/qunit/messages/messagesGeneral_legacyAPIs.qunit.js +158 -0
  880. package/test/sap/ui/core/qunit/messages/messagesUsage.qunit.js +29 -39
  881. package/test/sap/ui/core/qunit/messages/testsuite.messaging.base.qunit.js +9 -2
  882. package/test/sap/ui/core/qunit/model/Binding.qunit.js +8 -8
  883. package/test/sap/ui/core/qunit/model/ClientPropertyBinding.qunit.js +47 -0
  884. package/test/sap/ui/core/qunit/model/controlhelper/TreeBindingProxy.qunit.js +24 -14
  885. package/test/sap/ui/core/qunit/mvc/AnyView.qunit.js +7 -6
  886. package/test/sap/ui/core/qunit/mvc/AnyViewAsync.qunit.js +3 -2
  887. package/test/sap/ui/core/qunit/mvc/AsyncXMLView.qunit.js +5 -3
  888. package/test/sap/ui/core/qunit/mvc/Controller.qunit.js +3 -3
  889. package/test/sap/ui/core/qunit/mvc/View.qunit.js +5 -1
  890. package/test/sap/ui/core/qunit/mvc/XMLTemplateProcessorAsync_unavoidablyUsingInlineStyle.qunit.js +5 -4
  891. package/test/sap/ui/core/qunit/mvc/XMLTemplateProcessorRequireXML.qunit.js +8 -9
  892. package/test/sap/ui/core/qunit/mvc/XMLView.qunit.js +50 -44
  893. package/test/sap/ui/core/qunit/mvc/testdata/TypedViewWithRendererRenderer.js +2 -2
  894. package/test/sap/ui/core/qunit/mvc/testdata/stashed/OP.html +1 -1
  895. package/test/sap/ui/core/qunit/mvc/testdata/stashed/manifest.json +2 -1
  896. package/test/sap/ui/core/qunit/mvc/viewprocessing/ViewProcessing.qunit.js +18 -22
  897. package/test/sap/ui/core/qunit/mvc/viewprocessing/ViewProcessing_legacyAPIs.qunit.js +23 -27
  898. package/test/sap/ui/core/qunit/mvc_legacyAPIs/AnyViewAsync_legacyAPIs.qunit.js +10 -11
  899. package/test/sap/ui/core/qunit/mvc_legacyAPIs/AnyView_legacyAPIs.qunit.js +7 -6
  900. package/test/sap/ui/core/qunit/mvc_legacyAPIs/AsyncXMLView_legacyAPIs.qunit.js +5 -3
  901. package/test/sap/ui/core/qunit/mvc_legacyAPIs/HTMLView_legacyAPIs.qunit.js +8 -7
  902. package/test/sap/ui/core/qunit/mvc_legacyAPIs/XMLTemplateProcessorRequireXML_legacyAPIs.qunit.js +7 -7
  903. package/test/sap/ui/core/qunit/mvc_legacyAPIs/XMLView_legacyAPIs.qunit.js +45 -51
  904. package/test/sap/ui/core/qunit/odata/ODataAnnotations.qunit.js +52 -20
  905. package/test/sap/ui/core/qunit/odata/{ODataListBinding.qunit.js → ODataListBinding_legacyAPIs.qunit.js} +27 -0
  906. package/test/sap/ui/core/qunit/odata/ODataMessageParser.qunit.js +44 -48
  907. package/test/sap/ui/core/qunit/odata/ODataMessageParserNoFakeService.qunit.js +19 -15
  908. package/test/sap/ui/core/qunit/odata/ODataMetaModel.qunit.js +101 -29
  909. package/test/sap/ui/core/qunit/odata/ODataMetadata.qunit.js +17 -7
  910. package/test/sap/ui/core/qunit/odata/ODataTreeBindingAdapter.qunit.js +147 -89
  911. package/test/sap/ui/core/qunit/odata/ODataUtils.qunit.js +1 -0
  912. package/test/sap/ui/core/qunit/odata/_AnnotationHelperBasics.qunit.js +10 -4
  913. package/test/sap/ui/core/qunit/odata/data/ODataModelFakeService.js +1 -1
  914. package/test/sap/ui/core/qunit/odata/type/DateTimeBase.qunit.js +38 -12
  915. package/test/sap/ui/core/qunit/odata/type/ODataType.qunit.js +9 -0
  916. package/test/sap/ui/core/qunit/odata/type/TimeOfDay.qunit.js +33 -12
  917. package/test/sap/ui/core/qunit/odata/v2/CanonicalRequests.qunit.js +5 -4
  918. package/test/sap/ui/core/qunit/odata/v2/Context.qunit.js +12 -0
  919. package/test/sap/ui/core/qunit/odata/v2/ODataListBindingNoFakeService.qunit.js +485 -22
  920. package/test/sap/ui/core/qunit/odata/v2/ODataModel.integration.qunit.js +762 -90
  921. package/test/sap/ui/core/qunit/odata/v2/ODataModelNoFakeService.qunit.js +149 -6
  922. package/test/sap/ui/core/qunit/odata/v2/ODataTreeBindingFlatNoFakeService.qunit.js +21 -0
  923. package/test/sap/ui/core/qunit/odata/v2/ODataTreeBindingNoFakeService.qunit.js +1 -2
  924. package/test/sap/ui/core/qunit/odata/v2/ODataV2ListBinding.qunit.js +7 -207
  925. package/test/sap/ui/core/qunit/odata/v2/ODataV2ListBinding_Filter_legacyAPIs.qunit.js +281 -0
  926. package/test/sap/ui/core/qunit/odata/v2/ODataV2Model.qunit.js +9 -8
  927. package/test/sap/ui/core/qunit/odata/v2/ODataV2TreeBinding.qunit.js +1 -0
  928. package/test/sap/ui/core/qunit/odata/v2/V2ODataModel.qunit.js +95 -85
  929. package/test/sap/ui/core/qunit/odata/v2/V2ODataModelB.qunit.js +70 -67
  930. package/test/sap/ui/core/qunit/odata/v2/V2ODataModelDataState.qunit.js +19 -20
  931. package/test/sap/ui/core/qunit/odata/v2/testsuite.odatav2.qunit.js +4 -0
  932. package/test/sap/ui/core/qunit/odata/v4/Context.qunit.js +145 -35
  933. package/test/sap/ui/core/qunit/odata/v4/ODataBinding.qunit.js +64 -13
  934. package/test/sap/ui/core/qunit/odata/v4/ODataContextBinding.qunit.js +359 -78
  935. package/test/sap/ui/core/qunit/odata/v4/ODataListBinding.qunit.js +255 -33
  936. package/test/sap/ui/core/qunit/odata/v4/ODataModel.integration.qunit.js +2267 -148
  937. package/test/sap/ui/core/qunit/odata/v4/ODataModel.qunit.js +18 -17
  938. package/test/sap/ui/core/qunit/odata/v4/ODataParentBinding.qunit.js +19 -9
  939. package/test/sap/ui/core/qunit/odata/v4/ODataPropertyBinding.qunit.js +6 -27
  940. package/test/sap/ui/core/qunit/odata/v4/data/metadata.json +3 -1
  941. package/test/sap/ui/core/qunit/odata/v4/data/metadata.xml +2 -2
  942. package/test/sap/ui/core/qunit/odata/v4/lib/_AggregationCache.qunit.js +444 -53
  943. package/test/sap/ui/core/qunit/odata/v4/lib/_AggregationHelper.qunit.js +7 -8
  944. package/test/sap/ui/core/qunit/odata/v4/lib/_Cache.qunit.js +295 -161
  945. package/test/sap/ui/core/qunit/odata/v4/lib/_Helper.qunit.js +12 -22
  946. package/test/sap/ui/core/qunit/odata/v4/lib/_Requestor.qunit.js +108 -10
  947. package/test/sap/ui/core/qunit/odata/v4/lib/_V2Requestor.qunit.js +1 -1
  948. package/test/sap/ui/core/qunit/opa/Opa5PageObject.qunit.js +5 -6
  949. package/test/sap/ui/core/qunit/opa/OpaPlugin.qunit.js +35 -46
  950. package/test/sap/ui/core/qunit/opa/RecordReplay.qunit.js +13 -14
  951. package/test/sap/ui/core/qunit/opa/_ControlFinder.qunit.js +5 -4
  952. package/test/sap/ui/core/qunit/opa/actions/Action.qunit.js +6 -5
  953. package/test/sap/ui/core/qunit/opa/actions/EnterText.qunit.js +22 -21
  954. package/test/sap/ui/core/qunit/opa/actions/Press.qunit.js +60 -56
  955. package/test/sap/ui/core/qunit/opa/autowaiter/_cssAnimationWaiter.js +5 -7
  956. package/test/sap/ui/core/qunit/opa/autowaiter/_cssTransitionWaiter.js +5 -9
  957. package/test/sap/ui/core/qunit/opa/autowaiter/_jsAnimationWaiter.js +5 -6
  958. package/test/sap/ui/core/qunit/opa/autowaiter/_navigationContainerWaiter.js +5 -4
  959. package/test/sap/ui/core/qunit/opa/autowaiter/_resourceWaiter.js +21 -20
  960. package/test/sap/ui/core/qunit/opa/fixture/bindingPath.js +6 -5
  961. package/test/sap/ui/core/qunit/opa/matchers/Interactable.qunit.js +7 -5
  962. package/test/sap/ui/core/qunit/opa/matchers/LabelFor.qunit.js +4 -3
  963. package/test/sap/ui/core/qunit/opa/matchers/Sibling.qunit.js +4 -3
  964. package/test/sap/ui/core/qunit/opa/matchers/Visible.qunit.js +6 -5
  965. package/test/sap/ui/core/qunit/opa/matchers/_Busy.qunit.js +28 -27
  966. package/test/sap/ui/core/qunit/opa/matchers/_Editable.qunit.js +11 -10
  967. package/test/sap/ui/core/qunit/opa/matchers/_Enabled.qunit.js +11 -10
  968. package/test/sap/ui/core/qunit/opa/matchers/_Visitor.qunit.js +5 -4
  969. package/test/sap/ui/core/qunit/opa/opa5/actions.qunit.js +8 -7
  970. package/test/sap/ui/core/qunit/opa/opa5/basics.qunit.js +12 -17
  971. package/test/sap/ui/core/qunit/opa/opa5/logging.qunit.js +5 -6
  972. package/test/sap/ui/core/qunit/opa/opa5/matchers.qunit.js +6 -5
  973. package/test/sap/ui/core/qunit/opa/selectors/_BindingPath.js +10 -9
  974. package/test/sap/ui/core/qunit/opa/selectors/_ControlSelectorGenerator.js +6 -7
  975. package/test/sap/ui/core/qunit/opa/selectors/_ControlSelectorValidator.js +4 -3
  976. package/test/sap/ui/core/qunit/opa/selectors/_DropdownItem.js +4 -3
  977. package/test/sap/ui/core/qunit/opa/selectors/_GlobalID.js +4 -3
  978. package/test/sap/ui/core/qunit/opa/selectors/_LabelFor.js +4 -3
  979. package/test/sap/ui/core/qunit/opa/selectors/_Properties.js +33 -27
  980. package/test/sap/ui/core/qunit/opa/selectors/_Selector.js +9 -11
  981. package/test/sap/ui/core/qunit/opa/selectors/_TableRowItem.js +8 -9
  982. package/test/sap/ui/core/qunit/opa/selectors/_ViewID.js +5 -7
  983. package/test/sap/ui/core/qunit/performance/trace/Interaction.qunit.js +35 -28
  984. package/test/sap/ui/core/qunit/routing/Placeholder.qunit.js +11 -9
  985. package/test/sap/ui/core/qunit/routing/PlaceholderOptOut.qunit.js +5 -3
  986. package/test/sap/ui/core/qunit/routing/async/Router.qunit.js +57 -0
  987. package/test/sap/ui/core/qunit/routing/fixture/historyIframe/iframe/index.html +1 -1
  988. package/test/sap/ui/core/qunit/routing/fixture/router/component/2LevelsMultiNavTo/Child/Component.js +30 -0
  989. package/test/sap/ui/core/qunit/routing/fixture/router/component/2LevelsMultiNavTo/Child/manifest.json +25 -0
  990. package/test/sap/ui/core/qunit/routing/fixture/router/component/2LevelsMultiNavTo/Parent/Component.js +14 -0
  991. package/test/sap/ui/core/qunit/routing/fixture/router/component/2LevelsMultiNavTo/Parent/manifest.json +51 -0
  992. package/test/sap/ui/core/qunit/routing/fixture/router/component/2LevelsMultiNavTo/Parent/view/NotFound.view.xml +3 -0
  993. package/test/sap/ui/core/qunit/routing/fixture/router/component/2LevelsMultiNavTo/Parent/view/RootView.view.xml +5 -0
  994. package/test/sap/ui/core/qunit/rule/app/deprecatedJSViewUsage.qunit.js +4 -0
  995. package/test/sap/ui/core/qunit/rule/app/globalApiUsage.qunit.js +4 -0
  996. package/test/sap/ui/core/qunit/rule/app/jquerySapUsage.qunit.js +4 -0
  997. package/test/sap/ui/core/qunit/rule/app/syncXHR.qunit.js +28 -17
  998. package/test/sap/ui/core/qunit/rule/app/syncXHRBootstrap.qunit.js +7 -3
  999. package/test/sap/ui/core/qunit/rule/app/syncXHRBootstrapDebug.qunit.js +7 -3
  1000. package/test/sap/ui/core/qunit/rule/app/syncXHRBootstrapDebugBeforeBootstrap.js +4 -0
  1001. package/test/sap/ui/core/qunit/rule/config/asynchronousXMLViews.qunit.js +13 -19
  1002. package/test/sap/ui/core/qunit/rule/misc/silentEventBus.qunit.js +8 -7
  1003. package/test/sap/ui/core/qunit/rule/model/modelSupport.qunit.js +11 -2
  1004. package/test/sap/ui/core/qunit/rule/testsuite.rule.qunit.js +18 -0
  1005. package/test/sap/ui/core/qunit/support/techinfo/TechnicalInfoTestbench.html +3 -1
  1006. package/test/sap/ui/core/qunit/test/starter/find/index.html +1 -1
  1007. package/test/sap/ui/core/qunit/test/starter/find/main.js +13 -9
  1008. package/test/sap/ui/core/qunit/testsuite.core.framework.qunit.js +0 -6
  1009. package/test/sap/ui/core/qunit/testsuites/testsuite.base.configuration.qunit.js +1 -1
  1010. package/test/sap/ui/core/qunit/testsuites/testsuite.databinding.qunit.js +16 -6
  1011. package/test/sap/ui/core/qunit/testsuites/testsuite.foundation.enablement.qunit.js +7 -1
  1012. package/test/sap/ui/core/qunit/testsuites/testsuite.theming.qunit.js +48 -6
  1013. package/test/sap/ui/core/qunit/tmpl/Template.qunit.js +36 -35
  1014. package/test/sap/ui/core/qunit/types/DateFormat.qunit.js +13 -0
  1015. package/test/sap/ui/core/qunit/types/DateInterval.qunit.js +2 -2
  1016. package/test/sap/ui/core/qunit/util/BusyIndicatorNoCore.qunit.js +2 -2
  1017. package/test/sap/ui/core/qunit/util/InvisibleMessage.qunit.js +4 -4
  1018. package/test/sap/ui/core/qunit/util/LabelEnablement.qunit.js +27 -31
  1019. package/test/sap/ui/core/qunit/util/Popup.qunit.js +27 -27
  1020. package/test/sap/ui/core/qunit/util/ResponsivePaddingsEnablement.qunit.js +13 -9
  1021. package/test/sap/ui/core/qunit/util/XMLPreprocessor.qunit.js +60 -7
  1022. package/test/sap/ui/core/qunit/util/jQuery.sap.Version.qunit.js +5 -5
  1023. package/test/sap/ui/core/qunit/util/jQuery.sap.measure.qunit.js +1 -1
  1024. package/test/sap/ui/core/qunit/util/jquery.sap.dom.qunit.js +3 -2
  1025. package/test/sap/ui/core/qunit/util/reflection/JsControlTreeModifier.qunit.js +38 -21
  1026. package/test/sap/ui/core/qunit/util/reflection/XmlTreeModifier.qunit.js +64 -40
  1027. package/test/sap/ui/core/qunit/util/static/TechnicalInfoTestbenchInit.js +8 -2
  1028. package/test/sap/ui/core/qunit/util/support/TechnicalInfo.qunit.js +11 -10
  1029. package/test/sap/ui/core/qunit/webc/WebComponent.qunit.js +188 -0
  1030. package/test/sap/ui/core/qunit/webc/testsuite.webc.qunit.html +14 -0
  1031. package/test/sap/ui/core/qunit/webc/testsuite.webc.qunit.js +22 -0
  1032. package/test/sap/ui/core/qunit/xml/XMLPropertyBinding.qunit.js +69 -8
  1033. package/test/sap/ui/core/relnotes/changes-1.117.json +1 -34
  1034. package/test/sap/ui/core/relnotes/changes-1.118.json +110 -0
  1035. package/test/sap/ui/core/relnotes/changes-1.119.json +217 -0
  1036. package/test/sap/ui/core/resources/fastnav.js +3 -2
  1037. package/test/sap/ui/core/samples/ResponsiveDemo.html +3 -3
  1038. package/test/sap/ui/core/samples/components/commands/manifest.json +2 -2
  1039. package/test/sap/ui/core/samples/components/resourcesCSS/index.html +1 -1
  1040. package/test/sap/ui/core/samples/components/sample/manifest.json +2 -1
  1041. package/test/sap/ui/core/samples/databinding/DataBindingAsyncType.html +3 -2
  1042. package/test/sap/ui/core/samples/databinding/DatabindingMessages.html +158 -153
  1043. package/test/sap/ui/core/samples/databinding/ODatabindingMessages.html +7 -9
  1044. package/test/sap/ui/core/samples/databinding/UnitTable.view.xml +9 -2
  1045. package/test/sap/ui/core/samples/databinding/UnitTableMain.js +3 -4
  1046. package/test/sap/ui/core/samples/extensions/index_legacyAPIs.html +15 -13
  1047. package/test/sap/ui/core/samples/formatting/controller/ChooseFormatOptions.controller.js +3 -2
  1048. package/test/sap/ui/core/samples/formatting/manifest.json +2 -2
  1049. package/test/sap/ui/core/samples/mvc/ExtendedXMLViewEventHandlerSyntax.html +5 -3
  1050. package/test/sap/ui/core/samples/mvc/XMLViewAsync.html +62 -61
  1051. package/test/sap/ui/core/samples/mvc/XMLViewBindableAggregation.html +1 -1
  1052. package/test/sap/ui/core/samples/routing_legacyAPIs/AsyncViews.html +124 -123
  1053. package/test/sap/ui/core/terminologies/App.controller.js +3 -2
  1054. package/test/sap/ui/core/terminologies/App.view.xml +64 -64
  1055. package/test/sap/ui/core/tmpl_legacyAPIs/TemplateSimple.html +38 -37
  1056. package/test/sap/ui/core/util/PasteHelper.html +5 -4
  1057. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/firstItem-contextMenu.ref.lnk +1 -1
  1058. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/initial.ref.lnk +1 -1
  1059. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/lastItem-contextMenu.ref.lnk +1 -1
  1060. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/leftDownBtn-contextMenu.ref.lnk +1 -1
  1061. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/myButtonSample-contextMenu.ref.lnk +1 -1
  1062. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/rightDownBtn-contextMenu.ref.lnk +1 -1
  1063. package/test/testsuite/testframe.html +4 -4
  1064. package/src/ui5-boot.js +0 -50
  1065. package/test/sap/ui/core/qunit/CoreLock.qunit.js +0 -61
  1066. package/test/sap/ui/core/qunit/internal/ODataV4.qunit.js +0 -30
  1067. package/test/sap/ui/core/qunit/messages/MessageManager.qunit.js +0 -135
  1068. package/test/sap/ui/core/samples/databinding/DataBinding.html +0 -133
  1069. package/test/sap/ui/core/samples/databinding/DataBindingCalculatedFields.html +0 -227
  1070. package/test/sap/ui/core/samples/databinding/DataBindingCompositeTypes.html +0 -273
  1071. package/test/sap/ui/core/samples/databinding/DataBindingFormat.html +0 -294
  1072. package/test/sap/ui/core/samples/databinding/DataBindingList.html +0 -288
  1073. package/test/sap/ui/core/samples/databinding/DataBindingListNamedModel.html +0 -288
  1074. package/test/sap/ui/core/samples/databinding/DataBindingListXML.html +0 -278
  1075. package/test/sap/ui/core/samples/databinding/DataBindingMasterDetail.html +0 -117
  1076. package/test/sap/ui/core/samples/databinding/DataBindingMultiModel.html +0 -152
  1077. package/test/sap/ui/core/samples/databinding/DataBindingResourceModel.html +0 -119
  1078. package/test/sap/ui/core/samples/databinding/DataBindingSortingFiltering.html +0 -101
  1079. package/test/sap/ui/core/samples/databinding/DataBindingTree.html +0 -166
  1080. package/test/sap/ui/core/samples/databinding/DataBindingTreeFilter.html +0 -117
  1081. package/test/sap/ui/core/samples/databinding/DataBindingTreeFilterXML.html +0 -103
  1082. package/test/sap/ui/core/samples/databinding/DataBindingTreeLarge.html +0 -139
  1083. package/test/sap/ui/core/samples/databinding/DataBindingTreeWithArrays.html +0 -132
  1084. package/test/sap/ui/core/samples/databinding/DataBindingTwoWay.html +0 -156
  1085. package/test/sap/ui/core/samples/databinding/DataBindingTwoWayTable.html +0 -140
  1086. package/test/sap/ui/core/samples/databinding/DataBindingTypes.html +0 -265
  1087. package/test/sap/ui/core/samples/databinding/DataBindingValidation.html +0 -194
  1088. package/test/sap/ui/core/samples/databinding/DataBindingXML.html +0 -147
  1089. package/test/sap/ui/core/samples/databinding/DataBindingXMLView.html +0 -53
  1090. package/test/sap/ui/core/samples/databinding/testdata/ListBinding.view.xml +0 -9
  1091. package/test/sap/ui/core/samples/databinding/testdata/test.view.json +0 -15
  1092. package/test/sap/ui/core/samples/databinding/testdata/test.view.xml +0 -8
  1093. /package/test/sap/ui/core/qunit/{MasterDetail.qunit.js → MasterDetail_legacyAPIs.qunit.js} +0 -0
  1094. /package/test/sap/ui/core/qunit/odata/{ODataModel.qunit.js → ODataModel_legacyAPIs.qunit.js} +0 -0
  1095. /package/test/sap/ui/core/qunit/odata/{ODataSharedMetadata.qunit.js → ODataSharedMetadata_legacyAPIs.qunit.js} +0 -0
  1096. /package/test/sap/ui/core/qunit/odata/{ODataTreeBinding.qunit.js → ODataTreeBinding_legacyAPIs.qunit.js} +0 -0
@@ -14,6 +14,8 @@ sap.ui.define([
14
14
  "sap/ui/base/EventProvider",
15
15
  "sap/ui/base/SyncPromise",
16
16
  "sap/ui/core/Configuration",
17
+ "sap/ui/core/Messaging",
18
+ "sap/ui/core/Rendering",
17
19
  "sap/ui/core/mvc/Controller",
18
20
  "sap/ui/core/mvc/View",
19
21
  "sap/ui/model/ChangeReason",
@@ -34,10 +36,10 @@ sap.ui.define([
34
36
  // load Table resources upfront to avoid loading times > 1 second for the first test using Table
35
37
  "sap/ui/table/Table"
36
38
  ], function (Log, uid, UriParameters, ColumnListItem, CustomListItem, FlexBox, _MessageStrip, Text,
37
- Device, EventProvider, SyncPromise, Configuration, Controller, View, ChangeReason, Filter,
38
- FilterOperator, FilterType, Sorter, OperationMode, AnnotationHelper, ODataListBinding,
39
- ODataMetaModel, ODataModel, ODataPropertyBinding, ValueListType, _Helper, TestUtils,
40
- XMLHelper) {
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) {
41
43
  /*eslint no-sparse-arrays: 0, "max-len": ["error", {"code": 100,
42
44
  "ignorePattern": "/sap/opu/odata4/|\" :$|\" : \\{$|\\{meta>"}], */
43
45
  "use strict";
@@ -79,6 +81,110 @@ sap.ui.define([
79
81
  });
80
82
  }
81
83
 
84
+ /**
85
+ * Checks that the given list binding's _AggregationCache has a consistent state.
86
+ *
87
+ * @param {string} sTitle - A test title
88
+ * @param {object} assert - The QUnit assert object
89
+ * @param {sap.ui.model.odata.v4.ODataListBinding} oListBinding - A list binding
90
+ */
91
+ function checkAggregationCache(sTitle, assert, oListBinding) {
92
+ const aParentByLevel = [];
93
+
94
+ function checkCache(oCache) {
95
+ for (let i = 0, n = oCache.aElements.$created; i < n; i += 1) {
96
+ const oElement = oCache.aElements[i];
97
+ if (oElement) {
98
+ strictEqual("@$ui5.context.isTransient" in oElement, true, `created: ${i}`);
99
+ }
100
+ }
101
+ for (let i = oCache.aElements.$created, n = oCache.aElements.length; i < n; i += 1) {
102
+ const oElement = oCache.aElements[i];
103
+ if (oElement) {
104
+ strictEqual("@$ui5.context.isTransient" in oElement, false,
105
+ `not created: ${i}`);
106
+ }
107
+ }
108
+ strictEqual(oCache.aElements.$count === oCache.iLimit + oCache.iActiveElements, true,
109
+ `${oCache.aElements.$count} === ${oCache.iLimit} + ${oCache.iActiveElements}`);
110
+ }
111
+
112
+ function isKeepAlive(sPredicate) {
113
+ return oListBinding.getAllCurrentContexts()
114
+ .filter((oContext) => oContext.isEffectivelyKeptAlive())
115
+ .some((oContext) => oContext.getPath().endsWith(sPredicate));
116
+ }
117
+
118
+ function strictEqual(vActual, vExpected, sMyTitle) {
119
+ if (vActual !== vExpected) {
120
+ assert.strictEqual(vActual, vExpected, sMyTitle);
121
+ } // else: do not spam the output ;-)
122
+ }
123
+
124
+ function visitElements(aElements, bSkipByPredicate = false, iLevelOffset = 0) {
125
+ aElements.forEach((oElement) => {
126
+ const iIndex = _Helper.getPrivateAnnotation(oElement, "index");
127
+ // Note: "@$ui5.node.level" is outdated after #move!
128
+ const iLevel = oElement["@$ui5.node.level"] + iLevelOffset;
129
+ const oParent = aParentByLevel[iLevel];
130
+ const bPlaceholder = _Helper.hasPrivateAnnotation(oElement, "placeholder");
131
+
132
+ if (oParent) {
133
+ 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}`);
140
+ } else {
141
+ assert.ok(false, `${sTitle}: no known parent for level ${iLevel}`);
142
+ }
143
+
144
+ if (!bPlaceholder && !bSkipByPredicate) {
145
+ const checkByPredicate = function (sKey) {
146
+ const sPredicate = _Helper.getPrivateAnnotation(oElement, sKey);
147
+ if (sPredicate === undefined) {
148
+ return;
149
+ }
150
+ strictEqual(oListBinding.oCache.aElements.$byPredicate[sPredicate],
151
+ oElement, `${sTitle}: ${sPredicate} in $byPredicate`);
152
+ };
153
+
154
+ checkByPredicate("predicate");
155
+ checkByPredicate("transientPredicate");
156
+ }
157
+
158
+ const oCache = _Helper.getPrivateAnnotation(oElement, "cache");
159
+ if (oCache) {
160
+ checkCache(oCache);
161
+ aParentByLevel[iLevel + 1] = oCache;
162
+ }
163
+
164
+ const aSpliced = _Helper.getPrivateAnnotation(oElement, "spliced");
165
+ if (aSpliced) {
166
+ visitElements(aSpliced, true, iLevel + 1 - aSpliced[0]["@$ui5.node.level"]);
167
+ }
168
+ });
169
+ }
170
+
171
+ const aElements = oListBinding.oCache.aElements;
172
+ strictEqual(aElements.length, aElements.$count, `${sTitle}: $count`);
173
+ for (const sPredicate in aElements.$byPredicate) {
174
+ const oElement = aElements.$byPredicate[sPredicate];
175
+ strictEqual(oElement["@$ui5.context.isDeleted"] || aElements.includes(oElement)
176
+ || isKeepAlive(sPredicate),
177
+ true, `${sTitle}: $byPredicate[${sPredicate}] in aElements`);
178
+ }
179
+
180
+ for (let i = 0, n = oListBinding.getAggregation().expandTo || 1; i <= n; i += 1) {
181
+ // Note: level 0 or 1 is used for initial placeholders of 1st level cache!
182
+ aParentByLevel[i] = oListBinding.oCache.oFirstLevel;
183
+ }
184
+ checkCache(oListBinding.oCache.oFirstLevel);
185
+ visitElements(aElements);
186
+ }
187
+
82
188
  /**
83
189
  * Checks that the given promise is rejected with a cancellation error.
84
190
  *
@@ -123,6 +229,10 @@ sap.ui.define([
123
229
  return oCell.getText ? oCell.getText() : oCell.getValue();
124
230
  });
125
231
  }), aExpectedContent, sTitle);
232
+
233
+ if (oListBinding.getAggregation() && oListBinding.getAggregation().hierarchyQualifier) {
234
+ checkAggregationCache(sTitle, assert, oListBinding);
235
+ }
126
236
  }
127
237
 
128
238
  /**
@@ -365,7 +475,7 @@ sap.ui.define([
365
475
 
366
476
  oDocument = XMLHelper.parse(
367
477
  '<mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" xmlns:plugins="sap.m.plugins"'
368
- + ' xmlns:t="sap.ui.table"'
478
+ + ' xmlns:t="sap.ui.table" xmlns:trm="sap.ui.table.rowmodes"'
369
479
  + ' xmlns:template="http://schemas.sap.com/sapui5/extension/sap.ui.core.template/1">'
370
480
  + sViewXML
371
481
  + "</mvc:View>",
@@ -389,17 +499,28 @@ sap.ui.define([
389
499
  * @param {Document} oDocument The view as XML document
390
500
  */
391
501
  function xmlConvertGridTables(oDocument) {
392
- var oChildNode, aChildNodes, oColumn, oElement, i, j, aTableElements, oTemplate;
502
+ var oChildNode, aChildNodes, oColumn, oElement, i, j, aTableElements, oTemplate,
503
+ oRowMode, oFixedRowMode;
393
504
 
394
505
  aTableElements = oDocument.getElementsByTagNameNS("sap.ui.table", "Table");
395
506
  for (i = aTableElements.length - 1; i >= 0; i -= 1) {
396
507
  oElement = aTableElements[i];
397
508
 
509
+ if (oElement.hasAttribute("visibleRowCount")) {
510
+ oRowMode = document.createElementNS("sap.ui.table", "rowMode");
511
+ oElement.appendChild(oRowMode);
512
+ oFixedRowMode = document.createElementNS("sap.ui.table.rowmodes", "Fixed");
513
+ oFixedRowMode.setAttribute("rowCount", oElement.getAttribute("visibleRowCount"));
514
+ oRowMode.appendChild(oFixedRowMode);
515
+ oElement.removeAttribute("visibleRowCount");
516
+ }
517
+
398
518
  aChildNodes = oElement.childNodes;
399
519
  for (j = aChildNodes.length - 1; j >= 0; j -= 1) {
400
520
  oChildNode = aChildNodes[j];
401
521
  if (oChildNode.nodeType === Node.ELEMENT_NODE
402
- && oChildNode.localName !== "Column") {
522
+ && oChildNode.localName !== "Column"
523
+ && oChildNode.localName !== "rowMode") {
403
524
  oColumn = document.createElementNS("sap.ui.table", "Column");
404
525
  oElement.insertBefore(oColumn, oChildNode);
405
526
  oElement.removeChild(oChildNode);
@@ -530,7 +651,7 @@ sap.ui.define([
530
651
  // A list of expected requests with the properties method, url, headers, response
531
652
  this.aRequests = [];
532
653
 
533
- // If the "VisibleRowCountMode" of the sap.ui.table.* is "Auto", the table uses the
654
+ // If the "rowMode" of the sap.ui.table.* is "Auto", the table uses the
534
655
  // screen height (Device.resize.height) to compute the amount of contexts it requests
535
656
  // initially. Make sure that this is stable across devices.
536
657
  this._oSandbox.stub(Device.resize, "height").value(1000);
@@ -554,7 +675,7 @@ sap.ui.define([
554
675
  if (that.oModel) {
555
676
  that.oModel.destroy();
556
677
  }
557
- sap.ui.getCore().getMessageManager().removeAllMessages();
678
+ Messaging.removeAllMessages();
558
679
  // reset the language
559
680
  Configuration.setLanguage(sDefaultLanguage);
560
681
  }
@@ -665,9 +786,9 @@ sap.ui.define([
665
786
  }
666
787
  delete this.mListChanges[sControlId];
667
788
  }
668
- if (sap.ui.getCore().getUIDirty() || this.oModel && this.oModel.aPrerenderingTasks
669
- || sap.ui.getCore().getMessageManager().getMessageModel().getObject("/").length
670
- < this.aMessages.length) {
789
+
790
+ if (Rendering.isPending() || this.oModel && this.oModel.aPrerenderingTasks
791
+ || Messaging.getMessageModel().getObject("/").length < this.aMessages.length) {
671
792
  setTimeout(this.checkFinish.bind(this, assert), 10);
672
793
  } else if (this.resolve) {
673
794
  this.resolve();
@@ -681,7 +802,7 @@ sap.ui.define([
681
802
  * @param {object} assert The QUnit assert object
682
803
  */
683
804
  checkMessages : function (assert) {
684
- var aCurrentMessages = sap.ui.getCore().getMessageManager().getMessageModel()
805
+ var aCurrentMessages = Messaging.getMessageModel()
685
806
  .getObject("/").map(function (oMessage) {
686
807
  var aTargets = oMessage.getTargets().map(function (sTarget) {
687
808
  return normalizeUID(sTarget);
@@ -1583,7 +1704,7 @@ sap.ui.define([
1583
1704
 
1584
1705
  oView.setModel(that.oModel);
1585
1706
  // enable parse error messages in the message manager
1586
- sap.ui.getCore().getMessageManager().registerObject(oView, true);
1707
+ Messaging.registerObject(oView, true);
1587
1708
  // Place the view in the page so that it is actually rendered. In some situations,
1588
1709
  // esp. for the sap.ui.table.Table this is essential.
1589
1710
  oView.placeAt("qunit-fixture");
@@ -3255,6 +3376,65 @@ sap.ui.define([
3255
3376
  });
3256
3377
  });
3257
3378
 
3379
+ //*********************************************************************************************
3380
+ // Scenario: An ODCB for a BusinessPartner w/o cache is bound to "/SalesOrderList('1')". The
3381
+ // CompanyName is fetched late via requestProperty. Then the ODCB is bound to
3382
+ // "/SalesOrderList('2')", and requestProperty for the CompanyName must lead to another late
3383
+ // property request.
3384
+ // BCP: 2380079072
3385
+ QUnit.test("BCP: 2380079072", async function (assert) {
3386
+ const oModel = this.createSalesOrdersModel({autoExpandSelect : true});
3387
+ const sView = `
3388
+ <FlexBox id="form" binding="{SO_2_BP}">
3389
+ <Text id="bp" text="{BusinessPartnerID}"/>
3390
+ </FlexBox>`;
3391
+
3392
+ this.expectChange("bp");
3393
+
3394
+ await this.createView(assert, sView, oModel);
3395
+
3396
+ this.expectRequest("SalesOrderList('1')/SO_2_BP?$select=BusinessPartnerID",
3397
+ {BusinessPartnerID : "3"})
3398
+ .expectChange("bp", "3");
3399
+
3400
+ const oForm = this.oView.byId("form");
3401
+ oForm.setBindingContext(oModel.createBindingContext("/SalesOrderList('1')"));
3402
+
3403
+ await this.waitForChanges(assert, "1st bind");
3404
+
3405
+ this.expectRequest("SalesOrderList('1')/SO_2_BP?$select=BusinessPartnerID,CompanyName",
3406
+ {BusinessPartnerID : "3", CompanyName : "SAP"});
3407
+
3408
+ const oInnerBinding = oForm.getObjectBinding();
3409
+ const [sCompanyName1] = await Promise.all([
3410
+ oInnerBinding.getBoundContext().requestProperty("CompanyName"),
3411
+ this.waitForChanges(assert, "1st requestProperty")
3412
+ ]);
3413
+
3414
+ assert.strictEqual(sCompanyName1, "SAP");
3415
+
3416
+ this.expectRequest("SalesOrderList('2')?$select=SalesOrderID"
3417
+ + "&$expand=SO_2_BP($select=BusinessPartnerID)", {
3418
+ SalesOrderID : "2",
3419
+ SO_2_BP : {BusinessPartnerID : "4"}
3420
+ })
3421
+ .expectChange("bp", "4");
3422
+
3423
+ oForm.setBindingContext(oModel.bindContext("/SalesOrderList('2')").getBoundContext());
3424
+
3425
+ await this.waitForChanges(assert, "2nd bind");
3426
+
3427
+ this.expectRequest("SalesOrderList('2')/SO_2_BP?$select=BusinessPartnerID,CompanyName",
3428
+ {BusinessPartnerID : "4", CompanyName : "TECUM"});
3429
+
3430
+ const [sCompanyName2] = await Promise.all([
3431
+ oInnerBinding.getBoundContext().requestProperty("CompanyName"),
3432
+ this.waitForChanges(assert, "2nd requestProperty")
3433
+ ]);
3434
+
3435
+ assert.strictEqual(sCompanyName2, "TECUM");
3436
+ });
3437
+
3258
3438
  //*********************************************************************************************
3259
3439
  // Scenario: Return value context with data in cache, multiple context bindings w/o cache below,
3260
3440
  // multiple property bindings below these context bindings requesting their value late. One
@@ -8844,7 +9024,7 @@ sap.ui.define([
8844
9024
  } else if (i === 1) {
8845
9025
  that.oModel.resetChanges();
8846
9026
  } else if (i === 2) {
8847
- var oHeaderContext = oCreatedContext.getBinding().getHeaderContext();
9027
+ const oHeaderContext = oCreatedContext.getBinding().getHeaderContext();
8848
9028
 
8849
9029
  assert.throws(function () {
8850
9030
  // code under test (JIRA: CPOUI5ODATAV4-2014)
@@ -12548,6 +12728,16 @@ sap.ui.define([
12548
12728
  });
12549
12729
  });
12550
12730
 
12731
+ //*********************************************************************************************
12732
+ // Scenario: Enter an invalid value for worker-age for an ODataPropertyBinding and check that
12733
+ // parent Context.resetChanges() restores the value before.
12734
+ //*********************************************************************************************
12735
+ QUnit.test("reset invalid data state via context", function (assert) {
12736
+ return this.checkResetInvalidDataState(assert, function (oView) {
12737
+ return oView.byId("form").getBindingContext();
12738
+ });
12739
+ });
12740
+
12551
12741
  //*********************************************************************************************
12552
12742
  // Scenario: Enter an invalid value for worker-age for an ODataPropertyBinding and check that
12553
12743
  // ODataModel.resetChanges() restores the value before.
@@ -13212,7 +13402,11 @@ sap.ui.define([
13212
13402
  });
13213
13403
 
13214
13404
  //*********************************************************************************************
13215
- // Scenario: Call bound action on a context of a relative ListBinding
13405
+ // Scenario: Call bound action on a context of a relative ListBinding.
13406
+ //
13407
+ // Ensure that a Return Value Context is created and the structure of the path is same like the
13408
+ // binding parameter
13409
+ // JIRA: CPOUI5ODATAV4-2096
13216
13410
  QUnit.test("Read entity for a relative ListBinding, call bound action", function (assert) {
13217
13411
  var oModel = this.createTeaBusiModel(),
13218
13412
  that = this,
@@ -13238,15 +13432,24 @@ sap.ui.define([
13238
13432
  that.expectRequest({
13239
13433
  method : "POST",
13240
13434
  url : "TEAMS('42')/TEAM_2_EMPLOYEES('2')/"
13241
- + "com.sap.gateway.default.iwbep.tea_busi.v0001.AcChangeTeamOfEmployee",
13435
+ + "com.sap.gateway.default.iwbep.tea_busi.v0001.AcChangeTeamOfEmployee"
13436
+ + "?$expand=EMPLOYEE_2_TEAM($select=Team_Id)",
13242
13437
  payload : {TeamID : "TEAM_02"}
13243
- }, {ID : "2"});
13438
+ }, {
13439
+ EMPLOYEE_2_TEAM : {
13440
+ Team_Id : "TEAM_02"
13441
+ },
13442
+ ID : "2"
13443
+ });
13244
13444
  oAction.setParameter("TeamID", "TEAM_02");
13245
13445
 
13246
13446
  return Promise.all([
13247
13447
  // code under test
13248
- oAction.execute(),
13249
- // Note: no R.V.C. because path "/TEAMS('42')/TEAM_2_EMPLOYEES('2')" too long
13448
+ oAction.execute().then(function (oReturnValueContext) {
13449
+ assert.strictEqual(
13450
+ oReturnValueContext.getPath(),
13451
+ "/TEAMS('TEAM_02')/TEAM_2_EMPLOYEES('2')");
13452
+ }),
13250
13453
  that.waitForChanges(assert)
13251
13454
  ]);
13252
13455
  });
@@ -15103,16 +15306,16 @@ sap.ui.define([
15103
15306
  });
15104
15307
 
15105
15308
  //*********************************************************************************************
15106
- // Scenario: sap.ui.table.Table with VisibleRowCountMode="Auto" only calls ODLB.getContexts()
15309
+ // Scenario: sap.ui.table.Table with rowMode="Auto" only calls ODLB.getContexts()
15107
15310
  // after rendering (via setTimeout). This must not lead to separate requests for each table
15108
15311
  // cell resp. console errors due to data access via virtual context.
15109
15312
  // BCP 1770367083
15110
15313
  // Also tests that key properties are $select'ed for a sap.ui.table.Table with query options
15111
15314
  // different from $expand and $select in the binding parameters of the rows aggregation.
15112
- QUnit.test("sap.ui.table.Table with VisibleRowCountMode='Auto'", function (assert) {
15315
+ QUnit.test("sap.ui.table.Table with rowMode='Auto'", function (assert) {
15113
15316
  var sView = '\
15114
15317
  <t:Table id="table" rows="{path : \'/EMPLOYEES\', parameters : {$filter : \'AGE gt 42\'}}"\
15115
- visibleRowCountMode="Auto">\
15318
+ rowMode="Auto">\
15116
15319
  <t:Column>\
15117
15320
  <t:label>\
15118
15321
  <Label text="Name"/>\
@@ -20604,7 +20807,7 @@ sap.ui.define([
20604
20807
  });
20605
20808
 
20606
20809
  //*********************************************************************************************
20607
- // Scenario: sap.ui.table.Table with VisibleRowCountMode="Auto" and submit group 'API'
20810
+ // Scenario: sap.ui.table.Table with rowMode="Auto" and submit group 'API'
20608
20811
  // In the first step resume and immediately call submitBatch.
20609
20812
  // In the second step synchronously refresh with another group ID, change the filter and call
20610
20813
  // submitBatch. Check that the filter request is sent with this batch nevertheless.
@@ -20624,7 +20827,7 @@ sap.ui.define([
20624
20827
  var oListBinding,
20625
20828
  oModel = this.createTeaBusiModel({autoExpandSelect : true}),
20626
20829
  sView = '\
20627
- <t:Table id="table" visibleRowCountMode="Auto"\
20830
+ <t:Table id="table" rowMode="Auto"\
20628
20831
  rows="{path : \'/Equipments\', parameters : {$$groupId : \'api\'}, suspended : true}">\
20629
20832
  <t:Column>\
20630
20833
  <t:label>\
@@ -22004,8 +22207,7 @@ sap.ui.define([
22004
22207
  QUnit.test(sTitle, function (assert) {
22005
22208
  var oModel = this.createAggregationModel(),
22006
22209
  sView = '\
22007
- <t:Table fixedBottomRowCount="1" fixedRowCount="' + (bGrandTotalAtBottomOnly ? 0 : 1) + '"\
22008
- id="table" rows="{path : \'/BusinessPartners\', parameters : {\
22210
+ <t:Table id="table" rows="{path : \'/BusinessPartners\', parameters : {\
22009
22211
  $$aggregation : {\
22010
22212
  aggregate : {\
22011
22213
  SalesNumber : {grandTotal : true}\
@@ -22013,7 +22215,12 @@ sap.ui.define([
22013
22215
  grandTotalAtBottomOnly : ' + bGrandTotalAtBottomOnly + ',\
22014
22216
  group : {Country : {}}\
22015
22217
  }\
22016
- }}" threshold="0" visibleRowCount="' + (bGrandTotalAtBottomOnly ? 4 : 5) + '">\
22218
+ }}" threshold="0">\
22219
+ <t:rowMode>\
22220
+ <trm:Fixed rowCount="' + (bGrandTotalAtBottomOnly ? 4 : 5) + '"\
22221
+ fixedTopRowCount="' + (bGrandTotalAtBottomOnly ? 0 : 1) + '"\
22222
+ fixedBottomRowCount="1"/>\
22223
+ </t:rowMode>\
22017
22224
  <Text id="isExpanded" text="{= %{@$ui5.node.isExpanded} }"/>\
22018
22225
  <Text id="isTotal" text="{= %{@$ui5.node.isTotal} }"/>\
22019
22226
  <Text id="level" text="{= %{@$ui5.node.level} }"/>\
@@ -22429,7 +22636,7 @@ sap.ui.define([
22429
22636
  QUnit.test("Data Aggregation: grandTotalAtBottomOnly=true, just two rows", function (assert) {
22430
22637
  var oModel = this.createAggregationModel(),
22431
22638
  sView = '\
22432
- <t:Table fixedBottomRowCount="1" id="table" rows="{path : \'/BusinessPartners\', parameters : {\
22639
+ <t:Table id="table" rows="{path : \'/BusinessPartners\', parameters : {\
22433
22640
  $$aggregation : {\
22434
22641
  aggregate : {\
22435
22642
  SalesNumber : {grandTotal : true}\
@@ -22438,7 +22645,10 @@ sap.ui.define([
22438
22645
  groupLevels : [\'Country\',\'Region\'],\
22439
22646
  subtotalsAtBottomOnly : false\
22440
22647
  }\
22441
- }}" visibleRowCount="2">\
22648
+ }}">\
22649
+ <t:rowMode>\
22650
+ <trm:Fixed rowCount="2" fixedBottomRowCount="1"/>\
22651
+ </t:rowMode>\
22442
22652
  <Text id="isExpanded" text="{= %{@$ui5.node.isExpanded} }"/>\
22443
22653
  <Text id="isTotal" text="{= %{@$ui5.node.isTotal} }"/>\
22444
22654
  <Text id="level" text="{= %{@$ui5.node.level} }"/>\
@@ -23420,7 +23630,7 @@ sap.ui.define([
23420
23630
  oTable,
23421
23631
  sView = '\
23422
23632
  <Text id="count" text="{$count}"/>\
23423
- <t:Table fixedRowCount="1" firstVisibleRow="1" id="table" rows="{\
23633
+ <t:Table firstVisibleRow="1" id="table" rows="{\
23424
23634
  path : \'/BusinessPartners\',\
23425
23635
  parameters : {\
23426
23636
  $$aggregation : {\
@@ -23436,7 +23646,10 @@ sap.ui.define([
23436
23646
  $orderby : \'Region desc\'\
23437
23647
  },\
23438
23648
  filters : {path : \'AmountPerSale\', operator : \'GT\', value1 : 99}}"\
23439
- threshold="0" visibleRowCount="5">\
23649
+ threshold="0">\
23650
+ <t:rowMode>\
23651
+ <trm:Fixed rowCount="5" fixedTopRowCount="1"/>\
23652
+ </t:rowMode>\
23440
23653
  <Text id="country" text="{Country}"/>\
23441
23654
  <Text id="region" text="{Region}"/>\
23442
23655
  <Text id="salesNumber" text="{SalesNumber}"/>\
@@ -23524,7 +23737,7 @@ sap.ui.define([
23524
23737
  ],
23525
23738
  sView = '\
23526
23739
  <Text id="count" text="{$count}"/>\
23527
- <t:Table fixedRowCount="0" firstVisibleRow="1" id="table" rows="{\
23740
+ <t:Table firstVisibleRow="1" id="table" rows="{\
23528
23741
  path : \'/BusinessPartners\',\
23529
23742
  parameters : {\
23530
23743
  $$aggregation : {\
@@ -24594,6 +24807,10 @@ sap.ui.define([
24594
24807
  // The whole tree is expanded to two levels (JIRA: CPOUI5ODATAV4-2095).
24595
24808
  // Selection keeps a context implicitly alive (JIRA: CPOUI5ODATAV4-2053).
24596
24809
  // Ensure that unchanged $$aggregation is ignored (BCP: 2370045709).
24810
+ //
24811
+ // Retrieve "DrillState" property path via verbose ODLB#getAggregation & include it in the
24812
+ // downloadUrl
24813
+ // JIRA: CPOUI5ODATAV4-2275
24597
24814
  [false, true].forEach(function (bKeepAlive) {
24598
24815
  var sTitle = "Recursive Hierarchy: root is leaf; bKeepAlive=" + bKeepAlive;
24599
24816
 
@@ -24602,7 +24819,7 @@ sap.ui.define([
24602
24819
  = "/special/cases/Artists?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
24603
24820
  + "HierarchyNodes=$root/Artists,HierarchyQualifier='OrgChart'"
24604
24821
  + ",NodeProperty='_/NodeID',Levels=999)"
24605
- + "&$select=ArtistID,IsActiveEntity,_/DistanceFromRoot,_/NodeID"
24822
+ + "&$select=ArtistID,IsActiveEntity,_/DistanceFromRoot,_/DrillState,_/NodeID"
24606
24823
  + "&$expand=BestFriend($select=ArtistID,IsActiveEntity,Name)",
24607
24824
  oHeaderContext,
24608
24825
  oKeptAliveNode,
@@ -24672,11 +24889,12 @@ sap.ui.define([
24672
24889
  assert.deepEqual(oListBinding.getAggregation(/*bVerbose*/true), {
24673
24890
  hierarchyQualifier : "OrgChart",
24674
24891
  $DistanceFromRootProperty : "_/DistanceFromRoot",
24892
+ $DrillStateProperty : "_/DrillState",
24675
24893
  $NodeProperty : "_/NodeID"
24676
- }, "JIRA: CPOUI5ODATAV4-1961");
24894
+ }, "JIRA: CPOUI5ODATAV4-1961, CPOUI5ODATAV4-2275");
24677
24895
  // code under test
24678
24896
  assert.strictEqual(oListBinding.getDownloadUrl(), sExpectedDownloadUrl,
24679
- "JIRA: CPOUI5ODATAV4-1920");
24897
+ "JIRA: CPOUI5ODATAV4-1920, CPOUI5ODATAV4-2275");
24680
24898
 
24681
24899
  checkTable("root is leaf", assert, oTable, [
24682
24900
  "/Artists(ArtistID='0',IsActiveEntity=true)"
@@ -24738,7 +24956,8 @@ sap.ui.define([
24738
24956
  ]);
24739
24957
  }).then(function (aResults) {
24740
24958
  assert.strictEqual(aResults[0], "60");
24741
- assert.strictEqual(aResults[1], sExpectedDownloadUrl, "JIRA: CPOUI5ODATAV4-1920");
24959
+ assert.strictEqual(aResults[1], sExpectedDownloadUrl,
24960
+ "JIRA: CPOUI5ODATAV4-1920, CPOUI5ODATAV4-2275");
24742
24961
 
24743
24962
  that.expectRequest("Artists"
24744
24963
  + "?$select=ArtistID,IsActiveEntity,Messages,_/NodeID,defaultChannel"
@@ -24820,11 +25039,6 @@ sap.ui.define([
24820
25039
  ]);
24821
25040
  assert.strictEqual(oListBinding.getCount(), 1, "count of nodes"); // code under test
24822
25041
 
24823
- assert.throws(function () {
24824
- // code under test (JIRA: CPOUI5ODATAV4-1851)
24825
- oRoot.delete();
24826
- }, new Error("Cannot delete " + oRoot + " when using data aggregation"));
24827
-
24828
25042
  assert.throws(function () {
24829
25043
  // code under test (JIRA: CPOUI5ODATAV4-1851)
24830
25044
  oRoot.requestRefresh();
@@ -24874,7 +25088,7 @@ sap.ui.define([
24874
25088
  assert.strictEqual(oRoot.getProperty("defaultChannel"), "260", "360 has been ignored");
24875
25089
 
24876
25090
  that.expectMessages([]);
24877
- sap.ui.getCore().getMessageManager().removeAllMessages(); // clean up
25091
+ Messaging.removeAllMessages(); // clean up
24878
25092
 
24879
25093
  // Note: why is there no separate GET? because we have already loaded messages above!
24880
25094
  // that.expectRequest("Artists(ArtistID='0',IsActiveEntity=true)?$select=Messages");
@@ -25398,6 +25612,10 @@ sap.ui.define([
25398
25612
  //
25399
25613
  // Use relative ODLB with an initially suspended parent (JIRA: CPOUI5ODATAV4-1985 etc.)
25400
25614
  // Additionally, ODLB#getDownloadUrl is tested (JIRA: CPOUI5ODATAV4-1920. BCP: 2370011296).
25615
+ //
25616
+ // Ensure that a Return Value Context is created and the structure of the path is same like the
25617
+ // binding parameter
25618
+ // JIRA: CPOUI5ODATAV4-2096
25401
25619
  QUnit.test("Recursive Hierarchy: edit w/ currency", function (assert) {
25402
25620
  var sAction = "com.sap.gateway.default.iwbep.tea_busi.v0001.AcChangeTeamOfEmployee",
25403
25621
  oChild,
@@ -25472,9 +25690,9 @@ sap.ui.define([
25472
25690
  + "?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
25473
25691
  + "HierarchyNodes=$root/TEAMS('42')/TEAM_2_EMPLOYEES"
25474
25692
  + ",HierarchyQualifier='OrgChart',NodeProperty='ID',Levels=999)"
25475
- + "&$select=DistanceFromRoot,ID,MANAGER_ID,SALARY/BONUS_CURR"
25693
+ + "&$select=DistanceFromRoot,DrillState,ID,MANAGER_ID,SALARY/BONUS_CURR"
25476
25694
  + ",SALARY/YEARLY_BONUS_AMOUNT,TEAM_ID",
25477
- "JIRA: CPOUI5ODATAV4-1920");
25695
+ "JIRA: CPOUI5ODATAV4-1920, CPOUI5ODATAV4-2275");
25478
25696
 
25479
25697
  that.expectRequest("TEAMS('42')/TEAM_2_EMPLOYEES"
25480
25698
  + "?$apply=descendants($root/TEAMS('42')/TEAM_2_EMPLOYEES,OrgChart,ID"
@@ -25554,45 +25772,59 @@ sap.ui.define([
25554
25772
 
25555
25773
  that.expectRequest({
25556
25774
  method : "POST",
25557
- url : "TEAMS('42')/TEAM_2_EMPLOYEES('0')/" + sAction,
25558
- payload : {TeamID : "23"}
25775
+ url : "TEAMS('42')/TEAM_2_EMPLOYEES('0')/" + sAction
25776
+ + "?$expand=EMPLOYEE_2_TEAM($select=Team_Id)",
25777
+ payload : {TeamID : "TEAM_23"}
25559
25778
  }, {
25779
+ EMPLOYEE_2_TEAM : {
25780
+ Team_Id : "23"
25781
+ },
25560
25782
  ID : "0",
25561
25783
  MANAGER_ID : null,
25562
25784
  SALARY : { // "side effect"
25563
25785
  BONUS_CURR : "GBP",
25564
25786
  YEARLY_BONUS_AMOUNT : "23.23"
25565
25787
  },
25566
- TEAM_ID : "TEAM_23" // "side effect"
25788
+ TEAM_ID : "23" // "side effect"
25567
25789
  })
25568
25790
  .expectRequest({
25569
25791
  method : "POST",
25570
- url : "TEAMS('42')/TEAM_2_EMPLOYEES('1')/" + sAction,
25571
- payload : {TeamID : "42"}
25792
+ url : "TEAMS('42')/TEAM_2_EMPLOYEES('1')/" + sAction
25793
+ + "?$expand=EMPLOYEE_2_TEAM($select=Team_Id)",
25794
+ payload : {TeamID : "TEAM_42"}
25572
25795
  }, {
25796
+ EMPLOYEE_2_TEAM : {
25797
+ Team_Id : "42"
25798
+ },
25573
25799
  ID : "1",
25574
25800
  MANAGER_ID : "0",
25575
25801
  SALARY : { // "side effect"
25576
25802
  BONUS_CURR : "USD",
25577
25803
  YEARLY_BONUS_AMOUNT : "42.42"
25578
25804
  },
25579
- TEAM_ID : "TEAM_42" // "side effect"
25805
+ TEAM_ID : "42" // "side effect"
25580
25806
  });
25581
25807
 
25582
25808
  return Promise.all([
25583
25809
  oModel.bindContext(sAction + "(...)", oRoot)
25584
- .setParameter("TeamID", "23")
25810
+ .setParameter("TeamID", "TEAM_23")
25585
25811
  .execute()
25586
- .then(function (_oReturnValueContext) {
25587
- // Note: RVC has iGeneration === 2 instead of 0
25588
- //TODO assert.strictEqual(oReturnValueContext.getPath(), oRoot.getPath());
25812
+ .then(function (oReturnValueContext) {
25813
+ assert.strictEqual(oRoot.getPath(),
25814
+ "/TEAMS('42')/TEAM_2_EMPLOYEES('0')");
25815
+ assert.strictEqual(oReturnValueContext.getPath(),
25816
+ "/TEAMS('23')/TEAM_2_EMPLOYEES('0')");
25589
25817
  }),
25590
25818
  oModel.bindContext(sAction + "(...)", oChild)
25591
- .setParameter("TeamID", "42")
25819
+ .setParameter("TeamID", "TEAM_42")
25592
25820
  .execute()
25593
- .then(function (_oReturnValueContext) {
25821
+ .then(function (oReturnValueContext) {
25594
25822
  // Note: RVC has iGeneration === 2 instead of 0
25595
- //TODO assert.strictEqual(oReturnValueContext.getPath(), oChild.getPath());
25823
+ assert.notStrictEqual(oReturnValueContext, oChild);
25824
+ assert.strictEqual(oChild.getPath(),
25825
+ "/TEAMS('42')/TEAM_2_EMPLOYEES('1')");
25826
+ assert.strictEqual(oReturnValueContext.getPath(),
25827
+ "/TEAMS('42')/TEAM_2_EMPLOYEES('1')");
25596
25828
  }),
25597
25829
  that.waitForChanges(assert, "action")
25598
25830
  ]);
@@ -25601,8 +25833,8 @@ sap.ui.define([
25601
25833
  "/TEAMS('42')/TEAM_2_EMPLOYEES('0')",
25602
25834
  "/TEAMS('42')/TEAM_2_EMPLOYEES('1')"
25603
25835
  ], [
25604
- [true, 1, "0", "", "23.23", "GBP", "TEAM_23"],
25605
- [undefined, 2, "1", "0", "42.42", "USD", "TEAM_42"]
25836
+ [true, 1, "0", "", "23.23", "GBP", "23"],
25837
+ [undefined, 2, "1", "0", "42.42", "USD", "42"]
25606
25838
  ]);
25607
25839
  });
25608
25840
  });
@@ -25728,8 +25960,8 @@ sap.ui.define([
25728
25960
  + "?$apply=orderby(AGE%20desc)"
25729
25961
  + "/com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root/EMPLOYEES"
25730
25962
  + ",HierarchyQualifier='OrgChart',NodeProperty='ID',Levels=999)"
25731
- + "&$select=AGE,DistanceFromRoot,ID,MANAGER_ID,Name",
25732
- "JIRA: CPOUI5ODATAV4-1920");
25963
+ + "&$select=AGE,DistanceFromRoot,DrillState,ID,MANAGER_ID,Name",
25964
+ "JIRA: CPOUI5ODATAV4-1920, CPOUI5ODATAV4-2275");
25733
25965
 
25734
25966
  that.expectChange("count", "24");
25735
25967
 
@@ -26206,8 +26438,8 @@ sap.ui.define([
26206
26438
  + "/orderby(AGE%20desc)"
26207
26439
  + "/com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root/EMPLOYEES"
26208
26440
  + ",HierarchyQualifier='OrgChart',NodeProperty='ID',Levels=999)"
26209
- + "&$select=DistanceFromRoot,ID",
26210
- "JIRA: CPOUI5ODATAV4-1920");
26441
+ + "&$select=DistanceFromRoot,DrillState,ID",
26442
+ "JIRA: CPOUI5ODATAV4-1920, CPOUI5ODATAV4-2275");
26211
26443
 
26212
26444
  that.expectChange("count", "2");
26213
26445
 
@@ -26729,13 +26961,14 @@ sap.ui.define([
26729
26961
  }]
26730
26962
  });
26731
26963
 
26732
- // code under test
26733
- oXi.getBinding().getHeaderContext().requestSideEffects(["*"]);
26734
-
26735
26964
  // Note: side effect eventually destroys oBeta!
26736
26965
  oBeta = null;
26737
26966
 
26738
- return that.waitForChanges(assert, "request side effects");
26967
+ return Promise.all([
26968
+ // code under test
26969
+ oXi.getBinding().getHeaderContext().requestSideEffects(["*"]),
26970
+ that.waitForChanges(assert, "request side effects")
26971
+ ]);
26739
26972
  }).then(function () {
26740
26973
  checkTable("after request side effects", assert, oTable, [
26741
26974
  "/EMPLOYEES('2')",
@@ -27111,10 +27344,11 @@ sap.ui.define([
27111
27344
  }]
27112
27345
  });
27113
27346
 
27114
- // code under test
27115
- oAlpha.getBinding().getHeaderContext().requestSideEffects(["Name"]);
27116
-
27117
- return that.waitForChanges(assert, "request side effects");
27347
+ return Promise.all([
27348
+ // code under test
27349
+ oAlpha.getBinding().getHeaderContext().requestSideEffects(["Name"]),
27350
+ that.waitForChanges(assert, "request side effects")
27351
+ ]);
27118
27352
  }).then(function () {
27119
27353
  checkTable("after request side effects", assert, oTable, [
27120
27354
  "/EMPLOYEES('0')"
@@ -27317,10 +27551,11 @@ sap.ui.define([
27317
27551
  }]
27318
27552
  });
27319
27553
 
27320
- // code under test
27321
- oBeta.getBinding().getHeaderContext().requestSideEffects(["Name"]);
27322
-
27323
- return that.waitForChanges(assert, "request side effects");
27554
+ return Promise.all([
27555
+ // code under test
27556
+ oBeta.getBinding().getHeaderContext().requestSideEffects(["Name"]),
27557
+ that.waitForChanges(assert, "request side effects")
27558
+ ]);
27324
27559
  }).then(function () {
27325
27560
  checkTable("after request side effects", assert, oTable, [
27326
27561
  "/EMPLOYEES('0')",
@@ -27474,15 +27709,693 @@ sap.ui.define([
27474
27709
  });
27475
27710
  });
27476
27711
 
27712
+ //*********************************************************************************************
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.
27715
+ // JIRA: CPOUI5ODATAV4-2224
27716
+ QUnit.test("Recursive Hierarchy: delete top-level", async function (assert) {
27717
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
27718
+ const sView = `
27719
+ <Table id="table" items="{path : '/EMPLOYEES',
27720
+ parameters : {
27721
+ $$aggregation : {
27722
+ hierarchyQualifier : 'OrgChart'
27723
+ }
27724
+ }}">
27725
+ <Text text="{ID}"/>
27726
+ <Text id="name" text="{Name}"/>
27727
+ </Table>`;
27728
+
27729
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels"
27730
+ + "(HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart',NodeProperty='ID'"
27731
+ + ",Levels=1)"
27732
+ + "&$select=DrillState,ID,Name&$count=true&$skip=0&$top=100", {
27733
+ "@odata.count" : "1",
27734
+ value : [{
27735
+ ID : "0",
27736
+ Name : "Alpha"
27737
+ }]
27738
+ })
27739
+ .expectChange("name", ["Alpha"]);
27740
+
27741
+ await this.createView(assert, sView, oModel);
27742
+
27743
+ 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();
27758
+
27759
+ await Promise.all([
27760
+ checkCanceled(assert, oDeletePromise),
27761
+ this.waitForChanges(assert, "cancel delete")
27762
+ ]);
27763
+
27764
+ checkTable("after reinsert", assert, oTable, ["/EMPLOYEES('0')"], [
27765
+ ["0", "Alpha"]
27766
+ ], 1);
27767
+ });
27768
+
27769
+ //*********************************************************************************************
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.
27776
+ // ("Pi" is attached to a name when it is read a second time.)
27777
+ // JIRA: CPOUI5ODATAV4-2224
27778
+ QUnit.test("Recursive Hierarchy: delete second leaf", function (assert) {
27779
+ var oDeletePromise, oGamma, oTable;
27780
+
27781
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
27782
+ const sView = `
27783
+ <t:Table id="table" rows="{path : '/EMPLOYEES',
27784
+ parameters : {
27785
+ $$aggregation : {
27786
+ hierarchyQualifier : 'OrgChart'
27787
+ }
27788
+ }}" threshold="0" visibleRowCount="3" >
27789
+ <Text text="{= %{@$ui5.node.isExpanded} }"/>
27790
+ <Text text="{= %{@$ui5.node.level} }"/>
27791
+ <Text text="{ID}"/>
27792
+ <Text text="{MANAGER_ID}"/>
27793
+ <Text id="name" text="{Name}"/>
27794
+ </t:Table>`;
27795
+ const that = this;
27796
+
27797
+ // 0 Alpha
27798
+ // 1 Beta
27799
+ // 2 Gamma (deleted)
27800
+ // 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)
27802
+ // 5 Zeta (read via paging after delete)
27803
+ // 6 Eta (read via paging after reset)
27804
+ // 7 Theta
27805
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels"
27806
+ + "(HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart',NodeProperty='ID'"
27807
+ + ",Levels=1)"
27808
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=3", {
27809
+ "@odata.count" : "2",
27810
+ value : [{
27811
+ DrillState : "collapsed",
27812
+ ID : "0",
27813
+ MANAGER_ID : null,
27814
+ Name : "Alpha"
27815
+ }, {
27816
+ DrillState : "collapsed",
27817
+ ID : "7",
27818
+ MANAGER_ID : null,
27819
+ Name : "Theta"
27820
+ }]
27821
+ })
27822
+ .expectChange("name", ["Alpha", "Theta"]);
27823
+
27824
+ return this.createView(assert, sView, oModel).then(function () {
27825
+ oTable = that.oView.byId("table");
27826
+
27827
+ that.expectRequest("EMPLOYEES?"
27828
+ + "$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '0'),1)"
27829
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=3", {
27830
+ "@odata.count" : "6",
27831
+ value : [{
27832
+ DrillState : "collapsed",
27833
+ ID : "1",
27834
+ MANAGER_ID : "0",
27835
+ Name : "Beta"
27836
+ }, {
27837
+ DrillState : "leaf",
27838
+ ID : "2",
27839
+ MANAGER_ID : "0",
27840
+ Name : "Gamma"
27841
+ }, {
27842
+ DrillState : "leaf",
27843
+ ID : "3",
27844
+ MANAGER_ID : "0",
27845
+ Name : "Delta"
27846
+ }]
27847
+ })
27848
+ .expectChange("name", [, "Beta", "Gamma"]);
27849
+
27850
+ oTable.getRows()[0].getBindingContext().expand();
27851
+
27852
+ return that.waitForChanges(assert, "expand");
27853
+ }).then(function () {
27854
+ that.expectRequest("EMPLOYEES"
27855
+ + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '0'),1)"
27856
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$skip=3&$top=1", {
27857
+ value : [{
27858
+ DrillState : "leaf",
27859
+ ID : "4",
27860
+ MANAGER_ID : "0",
27861
+ Name : "Epsilon"
27862
+ }]
27863
+ })
27864
+ .expectChange("name", [,, "Gamma", "Delta", "Epsilon"]);
27865
+
27866
+ // code under test
27867
+ oTable.setFirstVisibleRow(2);
27868
+
27869
+ return that.waitForChanges(assert, "scroll down");
27870
+ }).then(function () {
27871
+ that.expectChange("name", ["Alpha", "Beta", "Gamma"]);
27872
+
27873
+ // code under test
27874
+ oTable.setFirstVisibleRow(0);
27875
+
27876
+ return that.waitForChanges(assert, "scroll up");
27877
+ }).then(function () {
27878
+ checkTable("before delete", assert, oTable, [
27879
+ "/EMPLOYEES('0')",
27880
+ "/EMPLOYEES('1')",
27881
+ "/EMPLOYEES('2')",
27882
+ "/EMPLOYEES('3')",
27883
+ "/EMPLOYEES('4')",
27884
+ "/EMPLOYEES('7')"
27885
+ ], [
27886
+ [true, 1, "0", "", "Alpha"],
27887
+ [false, 2, "1", "0", "Beta"],
27888
+ [undefined, 2, "2", "0", "Gamma"]
27889
+ ], 8);
27890
+
27891
+ that.expectChange("name", [,, "Delta"]);
27892
+
27893
+ oGamma = oTable.getRows()[2].getBindingContext();
27894
+ // code under test
27895
+ oDeletePromise = oGamma.delete("doNotSubmit");
27896
+
27897
+ return that.waitForChanges(assert, "delete");
27898
+ }).then(function () {
27899
+ checkTable("after delete", assert, oTable, [
27900
+ "/EMPLOYEES('0')",
27901
+ "/EMPLOYEES('1')",
27902
+ "/EMPLOYEES('3')",
27903
+ "/EMPLOYEES('4')",
27904
+ "/EMPLOYEES('7')"
27905
+ ], [
27906
+ [true, 1, "0", "", "Alpha"],
27907
+ [false, 2, "1", "0", "Beta"],
27908
+ [undefined, 2, "3", "0", "Delta"]
27909
+ ], 7);
27910
+
27911
+ that.expectRequest("EMPLOYEES?$select=ID,Name"
27912
+ + "&$filter=ID eq '0' or ID eq '1' or ID eq '3'&$top=3", {
27913
+ value : [{
27914
+ ID : "0",
27915
+ Name : "Alpha Pi"
27916
+ }, {
27917
+ ID : "1",
27918
+ Name : "Beta Pi"
27919
+ }, {
27920
+ ID : "3",
27921
+ Name : "Delta Pi"
27922
+ }]
27923
+ })
27924
+ .expectChange("name", ["Alpha Pi", "Beta Pi", "Delta Pi"]);
27925
+
27926
+ return Promise.all([
27927
+ // code under test
27928
+ oGamma.getBinding().getHeaderContext().requestSideEffects(["Name"]),
27929
+ that.waitForChanges(assert, "side effects")
27930
+ ]);
27931
+ }).then(function () {
27932
+ that.expectRequest("EMPLOYEES"
27933
+ + "?$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", {
27936
+ "@odata.count" : "5",
27937
+ value : [{
27938
+ DrillState : "leaf",
27939
+ ID : "4",
27940
+ MANAGER_ID : "0",
27941
+ Name : "Epsilon Pi"
27942
+ }, {
27943
+ DrillState : "collapsed",
27944
+ ID : "5",
27945
+ MANAGER_ID : "0",
27946
+ Name : "Zeta"
27947
+ }]
27948
+ })
27949
+ .expectChange("name", [,, "Delta Pi", "Epsilon Pi", "Zeta"]);
27950
+
27951
+ // code under test
27952
+ oTable.setFirstVisibleRow(2);
27953
+
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);
27976
+ }).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
+ that.expectRequest("EMPLOYEES"
27991
+ + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '0'),1)"
27992
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$skip=5&$top=1", {
27993
+ value : [{
27994
+ DrillState : "collapsed",
27995
+ ID : "6",
27996
+ MANAGER_ID : "0",
27997
+ Name : "Eta"
27998
+ }]
27999
+ })
28000
+ .expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels"
28001
+ + "(HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
28002
+ + ",NodeProperty='ID',Levels=1)"
28003
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$skip=1&$top=1", {
28004
+ value : [{
28005
+ DrillState : "collapsed",
28006
+ ID : "7",
28007
+ MANAGER_ID : null,
28008
+ Name : "Theta Pi"
28009
+ }]
28010
+ })
28011
+ .expectChange("name", [,,,,,, "Eta", "Theta Pi"]);
28012
+
28013
+ // code under test
28014
+ oTable.setFirstVisibleRow(5);
28015
+
28016
+ return that.waitForChanges(assert, "scroll to bottom");
28017
+ }).then(function () {
28018
+ checkTable("after scroll to bottom", assert, oTable, [
28019
+ "/EMPLOYEES('0')",
28020
+ "/EMPLOYEES('1')",
28021
+ "/EMPLOYEES('2')",
28022
+ "/EMPLOYEES('3')",
28023
+ "/EMPLOYEES('4')",
28024
+ "/EMPLOYEES('5')",
28025
+ "/EMPLOYEES('6')",
28026
+ "/EMPLOYEES('7')"
28027
+ ], [
28028
+ [false, 2, "5", "0", "Zeta"],
28029
+ [false, 2, "6", "0", "Eta"],
28030
+ [false, 1, "7", "", "Theta Pi"]
28031
+ ], 8);
28032
+ });
28033
+ });
28034
+
28035
+ //*********************************************************************************************
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.
28039
+ // * Expand Alpha and Beta.
28040
+ // * 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.
28045
+ // JIRA: CPOUI5ODATAV4-2224
28046
+ [false, true].forEach(function (bExpanded) {
28047
+ const sState = bExpanded ? "expanded" : "collapsed";
28048
+ QUnit.test(`Recursive Hierarchy: delete single ${sState} child`, async function (assert) {
28049
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
28050
+ const sView = `
28051
+ <Table id="table" items="{path : '/EMPLOYEES',
28052
+ parameters : {
28053
+ $$aggregation : {
28054
+ hierarchyQualifier : 'OrgChart'
28055
+ }
28056
+ }}">
28057
+ <Text id="expanded" text="{= %{@$ui5.node.isExpanded} }"/>
28058
+ <Text text="{= %{@$ui5.node.level} }"/>
28059
+ <Text text="{ID}"/>
28060
+ <Text text="{MANAGER_ID}"/>
28061
+ <Text id="name" text="{Name}"/>
28062
+ </Table>`;
28063
+
28064
+ // 0 Alpha
28065
+ // 1 Beta (deleted while Gamma is loaded)
28066
+ // 2 Gamma (must not get lost)
28067
+ // 3 Delta (only helps with the eventing)
28068
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels"
28069
+ + "(HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart',NodeProperty='ID'"
28070
+ + ",Levels=1)"
28071
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=100", {
28072
+ "@odata.count" : "2",
28073
+ value : [{
28074
+ DrillState : "collapsed",
28075
+ ID : "0",
28076
+ MANAGER_ID : null,
28077
+ Name : "Alpha"
28078
+ }, {
28079
+ DrillState : "collapsed",
28080
+ ID : "3",
28081
+ MANAGER_ID : null,
28082
+ Name : "Delta"
28083
+ }]
28084
+ })
28085
+ .expectChange("expanded", [false, false])
28086
+ .expectChange("name", ["Alpha", "Delta"]);
28087
+
28088
+ await this.createView(assert, sView, oModel);
28089
+
28090
+ this.expectRequest("EMPLOYEES"
28091
+ + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '0'),1)"
28092
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=100", {
28093
+ "@odata.count" : "1",
28094
+ value : [{
28095
+ DrillState : "collapsed",
28096
+ ID : "1",
28097
+ MANAGER_ID : "0",
28098
+ Name : "Beta"
28099
+ }]
28100
+ })
28101
+ .expectChange("expanded", [true,, false])
28102
+ .expectChange("name", [, "Beta", "Delta"]);
28103
+
28104
+ const oTable = this.oView.byId("table");
28105
+ oTable.getItems()[0].getBindingContext().expand();
28106
+
28107
+ await this.waitForChanges(assert, "expand Alpha");
28108
+
28109
+ this.expectRequest("EMPLOYEES"
28110
+ + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '1'),1)"
28111
+ + "&$select=DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=100", {
28112
+ "@odata.count" : "1",
28113
+ value : [{
28114
+ DrillState : "collapsed",
28115
+ ID : "2",
28116
+ MANAGER_ID : "1",
28117
+ Name : "Gamma"
28118
+ }]
28119
+ })
28120
+ .expectChange("expanded", [, true,, false])
28121
+ .expectChange("name", [,, "Gamma", "Delta"]);
28122
+
28123
+ const oBeta = oTable.getItems()[1].getBindingContext();
28124
+ oBeta.expand();
28125
+
28126
+ await this.waitForChanges(assert, "expand Beta");
28127
+
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);
28139
+
28140
+ if (bExpanded) {
28141
+ this.expectChange("expanded", [, false]); // Beta is collapsed before being deleted
28142
+ } else {
28143
+ this.expectChange("expanded", [, false])
28144
+ .expectChange("name", [,, "Delta"]);
28145
+
28146
+ oBeta.collapse();
28147
+
28148
+ await this.waitForChanges(assert, "collapse Beta");
28149
+
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);
28159
+ }
28160
+
28161
+ this.expectChange("expanded", [undefined]) // Alpha is now a leaf
28162
+ .expectChange("name", [, "Delta"]);
28163
+
28164
+ // code under test
28165
+ const oDeletePromise = oBeta.delete("doNotSubmit");
28166
+
28167
+ await this.waitForChanges(assert, "delete Beta");
28168
+
28169
+ checkTable("after delete", assert, oTable, [
28170
+ "/EMPLOYEES('0')",
28171
+ "/EMPLOYEES('3')"
28172
+ ], [
28173
+ [undefined, 1, "0", "", "Alpha"], // now a leaf
28174
+ [false, 1, "3", "", "Delta"]
28175
+ ], 2);
28176
+
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
+ }
28187
+
28188
+ // code under test
28189
+ oBeta.resetChanges();
28190
+
28191
+ await Promise.all([
28192
+ checkCanceled(assert, oDeletePromise),
28193
+ this.waitForChanges(assert, "cancel")
28194
+ ]);
28195
+
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);
28206
+
28207
+ this.expectChange("expanded", [, true, , false])
28208
+ .expectChange("name", [, , "Gamma", "Delta"]);
28209
+
28210
+ // code under test
28211
+ oBeta.expand();
28212
+
28213
+ await this.waitForChanges(assert, "expand again");
28214
+ }
28215
+
28216
+ checkTable("finally", assert, oTable, [
28217
+ "/EMPLOYEES('0')",
28218
+ "/EMPLOYEES('1')",
28219
+ "/EMPLOYEES('2')",
28220
+ "/EMPLOYEES('3')"
28221
+ ], [
28222
+ [true, 1, "0", "", "Alpha"],
28223
+ [true, 2, "1", "0", "Beta"],
28224
+ [false, 3, "2", "1", "Gamma"],
28225
+ [false, 1, "3", "", "Delta"]
28226
+ ], 4);
28227
+ });
28228
+ });
28229
+
28230
+ //*********************************************************************************************
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) {
28240
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
28241
+ const sView = `
28242
+ <Table id="table" items="{path : '/EMPLOYEES',
28243
+ parameters : {
28244
+ $$aggregation : {
28245
+ hierarchyQualifier : 'OrgChart'
28246
+ }
28247
+ }}">
28248
+ <Text id="expanded" text="{= %{@$ui5.node.isExpanded} }"/>
28249
+ <Text text="{= %{@$ui5.node.level} }"/>
28250
+ <Text text="{ID}"/>
28251
+ <Text text="{MANAGER_ID}"/>
28252
+ <Text id="name" text="{Name}"/>
28253
+ </Table>`;
28254
+
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",
28265
+ value : [{
28266
+ DrillState : "collapsed",
28267
+ ID : "0",
28268
+ MANAGER_ID : null,
28269
+ Name : "Alpha"
28270
+ }, {
28271
+ DrillState : "collapsed",
28272
+ ID : "1",
28273
+ MANAGER_ID : null,
28274
+ Name : "Beta"
28275
+ }, {
28276
+ DrillState : "collapsed",
28277
+ ID : "4",
28278
+ MANAGER_ID : null,
28279
+ Name : "Epsilon"
28280
+ }]
28281
+ })
28282
+ .expectChange("expanded", [false, false, false])
28283
+ .expectChange("name", ["Alpha", "Beta", "Epsilon"]);
28284
+
28285
+ await this.createView(assert, sView, oModel);
28286
+
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",
28291
+ value : [{
28292
+ DrillState : "collapsed",
28293
+ ID : "2",
28294
+ MANAGER_ID : "1",
28295
+ Name : "Gamma"
28296
+ }, {
28297
+ DrillState : "leaf",
28298
+ ID : "3",
28299
+ MANAGER_ID : "1",
28300
+ Name : "Delta"
28301
+ }]
28302
+ })
28303
+ .expectChange("expanded", [, true,, undefined, false])
28304
+ .expectChange("name", [,, "Gamma", "Delta", "Epsilon"]);
28305
+
28306
+ const oTable = this.oView.byId("table");
28307
+ oTable.getItems()[1].getBindingContext().expand();
28308
+
28309
+ await this.waitForChanges(assert, "expand Beta");
28310
+
28311
+ checkTable("before delete", assert, oTable, [
28312
+ "/EMPLOYEES('0')",
28313
+ "/EMPLOYEES('1')",
28314
+ "/EMPLOYEES('2')",
28315
+ "/EMPLOYEES('3')",
28316
+ "/EMPLOYEES('4')"
28317
+ ], [
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);
28324
+
28325
+ this.expectChange("expanded", [,,, false])
28326
+ .expectChange("name", [,,, "Epsilon"]);
28327
+
28328
+ // code under test
28329
+ const oDelta = oTable.getItems()[3].getBindingContext();
28330
+ const oDeleteDeltaPromise = oDelta.delete("doNotSubmit");
28331
+
28332
+ await this.waitForChanges(assert, "delete Delta");
28333
+
28334
+ this.expectChange("expanded", [undefined, false])
28335
+ .expectChange("name", ["Beta", "Epsilon"])
28336
+ .expectRequest("DELETE EMPLOYEES('2')")
28337
+ .expectRequest("DELETE EMPLOYEES('0')");
28338
+
28339
+ // code under test
28340
+ const oDeleteGammaPromise = oTable.getItems()[2].getBindingContext().delete();
28341
+ const oDeleteAlphaPromise = oTable.getItems()[0].getBindingContext().delete();
28342
+
28343
+ await Promise.all([
28344
+ oDeleteGammaPromise,
28345
+ oDeleteAlphaPromise,
28346
+ this.waitForChanges(assert, "delete Gamma and Alpha")
28347
+ ]);
28348
+
28349
+ checkTable("after delete", assert, oTable, [
28350
+ "/EMPLOYEES('1')",
28351
+ "/EMPLOYEES('4')"
28352
+ ], [
28353
+ [undefined, 1, "1", "", "Beta"],
28354
+ [false, 1, "4", "", "Epsilon"]
28355
+ ], 2);
28356
+
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"]);
28361
+
28362
+ // code under test
28363
+ oDelta.resetChanges();
28364
+
28365
+ await Promise.all([
28366
+ checkCanceled(assert, oDeleteDeltaPromise),
28367
+ this.waitForChanges(assert, "reinsert delta")
28368
+ ]);
28369
+
28370
+ checkTable("after reinsert", assert, oTable, [
28371
+ "/EMPLOYEES('1')",
28372
+ "/EMPLOYEES('3')",
28373
+ "/EMPLOYEES('4')"
28374
+ ], [
28375
+ [true, 1, "1", "", "Beta"],
28376
+ [undefined, 2, "3", "1", "Delta"],
28377
+ [false, 1, "4", "", "Epsilon"]
28378
+ ], 3);
28379
+ });
28380
+
27477
28381
  //*********************************************************************************************
27478
28382
  // Scenario: Show the single root node of a recursive hierarchy, which happens to be a leaf.
27479
- // Create two new child nodes underneath.
28383
+ // Create two new child nodes ("Beta", "Gamma") underneath.
27480
28384
  // Note: The "_Friend" navigation property is misused in order to have an artist play the role
27481
28385
  // of a hierarchy directory. This way, a draft root object is available (as needed by real
27482
28386
  // services).
27483
- // JIRA: CPOUI5ODATAV4-1592
28387
+ // JIRA: CPOUI5ODATAV4-2225
28388
+ //
28389
+ // Create new child and cancel immediately (JIRA: CPOUI5ODATAV4-2272)
28390
+ // @odata.bind in POST relative to resource path (BCP: 2380119648)
28391
+ //
28392
+ // Move "Gamma" so that "Beta" becomes its parent, then move it back again. Collapse the root,
28393
+ // request a side effect for all rows, and expand the root again. Start a move, but cancel it.
28394
+ // Move "Beta" so that "Gamma" becomes its parent (no change to context's index, but a persisted
28395
+ // node (again) becomes "created persisted"). Observe property change events for "@odata.etag".
28396
+ // JIRA: CPOUI5ODATAV4-2226
27484
28397
  QUnit.test("Recursive Hierarchy: create new children", function (assert) {
27485
- var oChild, oListBinding, fnRespond, oRoot, oTable;
28398
+ var oBeta, oBetaCreated, oGamma, oGammaCreated, oListBinding, fnRespond, oRoot, oTable;
27486
28399
 
27487
28400
  const oModel = this.createSpecialCasesModel({autoExpandSelect : true});
27488
28401
  const sFriend = "/Artists(ArtistID='99',IsActiveEntity=false)/_Friend";
@@ -27493,22 +28406,22 @@ sap.ui.define([
27493
28406
  hierarchyQualifier : 'OrgChart'
27494
28407
  }
27495
28408
  }}" threshold="0" visibleRowCount="3">
28409
+ <Text text="{= %{@$ui5.context.isTransient} }"/>
27496
28410
  <Text text="{= %{@$ui5.node.isExpanded} }"/>
27497
28411
  <Text text="{= %{@$ui5.node.level} }"/>
28412
+ <Text id="etag" text="{= %{@odata.etag} }"/>
27498
28413
  <Text id="name" text="{Name}"/>
27499
28414
  </t:Table>`;
27500
28415
  const that = this;
27501
28416
 
27502
- this.expectRequest({
27503
- batchNo : 1,
27504
- url : sFriend.slice(1) + "?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
27505
- + "HierarchyNodes=$root" + sFriend
27506
- + ",HierarchyQualifier='OrgChart',NodeProperty='_/NodeID',Levels=1)"
27507
- + "&$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID"
27508
- + "&$count=true&$skip=0&$top=3"
27509
- }, {
28417
+ this.expectRequest(sFriend.slice(1) + "?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
28418
+ + "HierarchyNodes=$root" + sFriend
28419
+ + ",HierarchyQualifier='OrgChart',NodeProperty='_/NodeID',Levels=1)"
28420
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID"
28421
+ + "&$count=true&$skip=0&$top=3", {
27510
28422
  "@odata.count" : "1",
27511
28423
  value : [{
28424
+ "@odata.etag" : "etag0.0",
27512
28425
  ArtistID : "0",
27513
28426
  IsActiveEntity : false,
27514
28427
  Name : "Alpha",
@@ -27520,6 +28433,7 @@ sap.ui.define([
27520
28433
  }
27521
28434
  }]
27522
28435
  })
28436
+ .expectChange("etag", ["etag0.0"])
27523
28437
  .expectChange("name", ["Alpha"]);
27524
28438
 
27525
28439
  return this.createView(assert, sView, oModel).then(function () {
@@ -27530,9 +28444,9 @@ sap.ui.define([
27530
28444
  checkTable("root is leaf", assert, oTable, [
27531
28445
  sFriend + "(ArtistID='0',IsActiveEntity=false)"
27532
28446
  ], [
27533
- [undefined, 1, "Alpha"],
27534
- ["", "", ""],
27535
- ["", "", ""]
28447
+ [undefined, undefined, 1, "etag0.0", "Alpha"],
28448
+ ["", "", "", "", ""],
28449
+ ["", "", "", "", ""]
27536
28450
  ]);
27537
28451
  assert.strictEqual(oRoot.getIndex(), 0);
27538
28452
 
@@ -27541,12 +28455,20 @@ sap.ui.define([
27541
28455
  oListBinding.create({}, /*bSkipRefresh*/true);
27542
28456
  }); // TypeError: Cannot read properties of undefined (reading 'getCanonicalPath')
27543
28457
 
27544
- that.expectChange("name", [, "Beta"])
28458
+ // code under test (JIRA: CPOUI5ODATAV4-2272)
28459
+ const oLostChild = oListBinding.create({
28460
+ "@$ui5.node.parent" : oRoot,
28461
+ Name : "n/a"
28462
+ }, /*bSkipRefresh*/true);
28463
+ oModel.resetChanges();
28464
+
28465
+ that.expectChange("etag", [, undefined])
28466
+ .expectChange("name", [, "Beta"])
27545
28467
  .expectRequest({
27546
28468
  method : "POST",
27547
28469
  url : sFriend.slice(1),
27548
28470
  payload : {
27549
- "BestFriend@odata.bind" : "Artists(ArtistID='0',IsActiveEntity=false)",
28471
+ "BestFriend@odata.bind" : "../Artists(ArtistID='0',IsActiveEntity=false)",
27550
28472
  Name : "Beta"
27551
28473
  }
27552
28474
  }, new Promise(function (resolve) {
@@ -27559,29 +28481,34 @@ sap.ui.define([
27559
28481
  }));
27560
28482
 
27561
28483
  // code under test
27562
- oChild = oListBinding.create({
28484
+ oBeta = oListBinding.create({
27563
28485
  "@$ui5.node.parent" : oRoot,
27564
28486
  Name : "Beta"
27565
28487
  }, /*bSkipRefresh*/true);
28488
+ oBetaCreated = oBeta.created();
27566
28489
 
27567
- return that.waitForChanges(assert, "create 1st child");
28490
+ return Promise.all([
28491
+ checkCanceled(assert, oLostChild.created()),
28492
+ that.waitForChanges(assert, "create 1st child")
28493
+ ]);
27568
28494
  }).then(function () {
27569
28495
  checkTable("during creation", assert, oTable, [
27570
28496
  sFriend + "(ArtistID='0',IsActiveEntity=false)",
27571
28497
  sFriend + "($uid=...)"
27572
28498
  ], [
27573
- [true, 1, "Alpha"],
27574
- [undefined, 2, "Beta"],
27575
- ["", "", ""]
28499
+ [undefined, true, 1, "etag0.0", "Alpha"],
28500
+ [true, undefined, 2, "", "Beta"],
28501
+ ["", "", "", "", ""]
27576
28502
  ]);
27577
- assert.strictEqual(oChild.getIndex(), 1);
28503
+ assert.strictEqual(oBeta.getIndex(), 1);
27578
28504
 
27579
- that.expectChange("name", [, "Beta: β"]);
28505
+ that.expectChange("etag", [, "etag1.0"])
28506
+ .expectChange("name", [, "Beta: β"]);
27580
28507
 
27581
28508
  fnRespond();
27582
28509
 
27583
28510
  return Promise.all([
27584
- oChild.created(),
28511
+ oBetaCreated,
27585
28512
  that.waitForChanges(assert, "respond")
27586
28513
  ]);
27587
28514
  }).then(function () {
@@ -27589,12 +28516,12 @@ sap.ui.define([
27589
28516
  sFriend + "(ArtistID='0',IsActiveEntity=false)",
27590
28517
  sFriend + "(ArtistID='1',IsActiveEntity=false)"
27591
28518
  ], [
27592
- [true, 1, "Alpha"],
27593
- [undefined, 2, "Beta: β"],
27594
- ["", "", ""]
28519
+ [undefined, true, 1, "etag0.0", "Alpha"],
28520
+ [false, undefined, 2, "etag1.0", "Beta: β"],
28521
+ ["", "", "", "", ""]
27595
28522
  ]);
27596
- assert.strictEqual(oChild.getIndex(), 1);
27597
- assert.deepEqual(oChild.getObject(), {
28523
+ assert.strictEqual(oBeta.getIndex(), 1);
28524
+ assert.deepEqual(oBeta.getObject(), {
27598
28525
  "@$ui5.context.isTransient" : false,
27599
28526
  "@$ui5.node.level" : 2,
27600
28527
  "@odata.etag" : "etag1.0",
@@ -27602,47 +28529,890 @@ sap.ui.define([
27602
28529
  IsActiveEntity : false,
27603
28530
  Name : "Beta: β"
27604
28531
  });
28532
+ assert.strictEqual(oBeta.isTransient(), false, "created persisted");
28533
+ assert.strictEqual(oBeta.created(), oBetaCreated);
27605
28534
 
27606
- that.expectChange("name", [, "Gamma", "Beta: β"])
28535
+ // code under test (JIRA: CPOUI5ODATAV4-2272)
28536
+ const oLostChild = oListBinding.create({
28537
+ "@$ui5.node.parent" : oRoot,
28538
+ Name : "n/a"
28539
+ }, /*bSkipRefresh*/true);
28540
+ oModel.resetChanges();
28541
+
28542
+ that.expectChange("etag", [, undefined, "etag1.0"])
28543
+ .expectChange("name", [, "Gamma", "Beta: β"])
27607
28544
  .expectRequest({
27608
28545
  method : "POST",
27609
28546
  url : sFriend.slice(1),
27610
28547
  payload : {
27611
- "BestFriend@odata.bind" : "Artists(ArtistID='0',IsActiveEntity=false)",
28548
+ "BestFriend@odata.bind" : "../Artists(ArtistID='0',IsActiveEntity=false)",
27612
28549
  Name : "Gamma"
27613
28550
  }
27614
28551
  }, {
28552
+ "@odata.etag" : "etag2.0",
27615
28553
  ArtistID : "2",
27616
28554
  IsActiveEntity : false,
27617
28555
  Name : "Gamma: γ" // side effect
27618
28556
  })
28557
+ .expectChange("etag", [, "etag2.0"])
27619
28558
  .expectChange("name", [, "Gamma: γ"]);
27620
28559
 
27621
28560
  // code under test
27622
- oChild = oListBinding.create({
28561
+ oGamma = oListBinding.create({
27623
28562
  "@$ui5.node.parent" : oRoot,
27624
28563
  Name : "Gamma"
27625
28564
  }, /*bSkipRefresh*/true);
28565
+ oGammaCreated = oGamma.created();
27626
28566
 
27627
- assert.strictEqual(oChild.getIndex(), 1);
28567
+ assert.strictEqual(oGamma.getIndex(), 1);
27628
28568
 
27629
28569
  return Promise.all([
27630
- oChild.created(),
28570
+ checkCanceled(assert, oLostChild.created()),
28571
+ oGammaCreated,
27631
28572
  that.waitForChanges(assert, "create 2nd child")
27632
28573
  ]);
27633
28574
  }).then(function () {
27634
- checkTable("after creation", assert, oTable, [
28575
+ checkTable("after 2nd creation", assert, oTable, [
28576
+ sFriend + "(ArtistID='0',IsActiveEntity=false)",
28577
+ sFriend + "(ArtistID='2',IsActiveEntity=false)",
28578
+ sFriend + "(ArtistID='1',IsActiveEntity=false)"
28579
+ ], [
28580
+ [undefined, true, 1, "etag0.0", "Alpha"],
28581
+ [false, undefined, 2, "etag2.0", "Gamma: γ"],
28582
+ [false, undefined, 2, "etag1.0", "Beta: β"]
28583
+ ]);
28584
+ assert.strictEqual(oGamma.isTransient(), false, "created persisted");
28585
+ assert.strictEqual(oGamma.created(), oGammaCreated);
28586
+
28587
+ that.expectRequest({
28588
+ headers : {
28589
+ "If-Match" : "etag2.0",
28590
+ Prefer : "return=minimal"
28591
+ },
28592
+ method : "PATCH",
28593
+ url : "Artists(ArtistID='2',IsActiveEntity=false)",
28594
+ payload : {
28595
+ "BestFriend@odata.bind" : "Artists(ArtistID='1',IsActiveEntity=false)"
28596
+ }
28597
+ }, null, {ETag : "etag2.1"}) // 204 No Content
28598
+ .expectChange("etag", [, "etag2.1"]) // Note: property changed before context moved
28599
+ .expectChange("etag", [, "etag1.0", "etag2.1"])
28600
+ .expectChange("name", [, "Beta: β", "Gamma: γ"]);
28601
+
28602
+ return Promise.all([
28603
+ // code under test
28604
+ oGamma.move({parent : oBeta}),
28605
+ that.waitForChanges(assert, "move")
28606
+ ]);
28607
+ }).then(function () {
28608
+ checkTable("after move", assert, oTable, [
28609
+ sFriend + "(ArtistID='0',IsActiveEntity=false)",
28610
+ sFriend + "(ArtistID='1',IsActiveEntity=false)",
28611
+ sFriend + "(ArtistID='2',IsActiveEntity=false)"
28612
+ ], [
28613
+ [undefined, true, 1, "etag0.0", "Alpha"],
28614
+ [false, true, 2, "etag1.0", "Beta: β"],
28615
+ [false, undefined, 3, "etag2.1", "Gamma: γ"]
28616
+ ]);
28617
+
28618
+ assert.strictEqual(oBeta.getIndex(), 1);
28619
+ assert.deepEqual(oBeta.getObject(), {
28620
+ "@$ui5.context.isTransient" : false,
28621
+ "@$ui5.node.isExpanded" : true,
28622
+ "@$ui5.node.level" : 2,
28623
+ "@odata.etag" : "etag1.0",
28624
+ ArtistID : "1",
28625
+ IsActiveEntity : false,
28626
+ Name : "Beta: β"
28627
+ });
28628
+ assert.strictEqual(oBeta.isTransient(), false, "created persisted");
28629
+ assert.strictEqual(oBeta.created(), oBetaCreated);
28630
+
28631
+ assert.strictEqual(oGamma.getIndex(), 2);
28632
+ assert.deepEqual(oGamma.getObject(), {
28633
+ "@$ui5.context.isTransient" : false,
28634
+ "@$ui5.node.level" : 3,
28635
+ "@odata.etag" : "etag2.1", // updated
28636
+ ArtistID : "2",
28637
+ IsActiveEntity : false,
28638
+ Name : "Gamma: γ"
28639
+ });
28640
+ assert.strictEqual(oGamma.isTransient(), false, "created persisted");
28641
+ assert.strictEqual(oGamma.created(), oGammaCreated, "unchanged");
28642
+
28643
+ //TODO assert.throws(function () {
28644
+ // // code under test
28645
+ // oRoot.move({parent : oGamma});
28646
+ // }, new Error("Unsupported parent context: " + oGamma));
28647
+
28648
+ that.expectRequest({
28649
+ headers : {
28650
+ "If-Match" : "etag2.1",
28651
+ Prefer : "return=minimal"
28652
+ },
28653
+ method : "PATCH",
28654
+ url : "Artists(ArtistID='2',IsActiveEntity=false)",
28655
+ payload : {
28656
+ "BestFriend@odata.bind" : "Artists(ArtistID='0',IsActiveEntity=false)"
28657
+ }
28658
+ }, null, {ETag : "etag2.2"}) // 204 No Content
28659
+ .expectChange("etag", [,, "etag2.2"]) // Note: property changed before context moved
28660
+ .expectChange("etag", [, "etag2.2", "etag1.0"])
28661
+ .expectChange("name", [, "Gamma: γ", "Beta: β"]);
28662
+
28663
+ return Promise.all([
28664
+ // code under test
28665
+ oGamma.move({parent : oRoot}),
28666
+ that.waitForChanges(assert, "move back")
28667
+ ]);
28668
+ }).then(function () {
28669
+ checkTable("after move back", assert, oTable, [
28670
+ sFriend + "(ArtistID='0',IsActiveEntity=false)",
28671
+ sFriend + "(ArtistID='2',IsActiveEntity=false)",
28672
+ sFriend + "(ArtistID='1',IsActiveEntity=false)"
28673
+ ], [
28674
+ [undefined, true, 1, "etag0.0", "Alpha"],
28675
+ [false, undefined, 2, "etag2.2", "Gamma: γ"], // moved *before* all created rows
28676
+ [false, undefined, 2, "etag1.0", "Beta: β"]
28677
+ ]);
28678
+
28679
+ assert.strictEqual(oGamma.getIndex(), 1);
28680
+ assert.deepEqual(oGamma.getObject(), {
28681
+ "@$ui5.context.isTransient" : false,
28682
+ "@$ui5.node.level" : 2,
28683
+ "@odata.etag" : "etag2.2", // updated
28684
+ ArtistID : "2",
28685
+ IsActiveEntity : false,
28686
+ Name : "Gamma: γ"
28687
+ });
28688
+ assert.strictEqual(oGamma.isTransient(), false, "created persisted");
28689
+ assert.strictEqual(oGamma.created(), oGammaCreated, "unchanged");
28690
+
28691
+ assert.strictEqual(oBeta.getIndex(), 2);
28692
+ assert.deepEqual(oBeta.getObject(), {
28693
+ "@$ui5.context.isTransient" : false,
28694
+ "@$ui5.node.level" : 2,
28695
+ "@odata.etag" : "etag1.0",
28696
+ ArtistID : "1",
28697
+ IsActiveEntity : false,
28698
+ Name : "Beta: β"
28699
+ });
28700
+ assert.strictEqual(oBeta.isTransient(), false, "created persisted");
28701
+ assert.strictEqual(oBeta.created(), oBetaCreated);
28702
+
28703
+ // code under test
28704
+ oRoot.collapse();
28705
+
28706
+ return that.waitForChanges(assert, "collapse root");
28707
+ }).then(function () {
28708
+ checkTable("after collapse", assert, oTable, [
28709
+ sFriend + "(ArtistID='0',IsActiveEntity=false)"
28710
+ ], [
28711
+ [undefined, false, 1, "etag0.0", "Alpha"],
28712
+ ["", "", "", "", ""],
28713
+ ["", "", "", "", ""]
28714
+ ]);
28715
+
28716
+ that.expectRequest(sFriend.slice(1) + "?$select=ArtistID,IsActiveEntity,Name,_/NodeID"
28717
+ + "&$filter=ArtistID eq '0' and IsActiveEntity eq false", {
28718
+ value : [{
28719
+ "@odata.etag" : "etag0.1",
28720
+ ArtistID : "0",
28721
+ IsActiveEntity : false,
28722
+ Name : "Alpha #1", // "side effect"
28723
+ _ : null // not available w/ RAP for a non-hierarchical request
28724
+ }]
28725
+ })
28726
+ .expectChange("etag", ["etag0.1"])
28727
+ .expectChange("name", ["Alpha #1"]);
28728
+
28729
+ oBeta = oGamma = null; // Note: side effect eventually destroys these!
28730
+
28731
+ return Promise.all([
28732
+ // code under test
28733
+ oListBinding.getHeaderContext().requestSideEffects(["Name"]),
28734
+ that.waitForChanges(assert, "side effect: Name for all rows")
28735
+ ]);
28736
+ }).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!
28742
+ "@odata.etag" : "etag2.3", // updated
28743
+ ArtistID : "2",
28744
+ IsActiveEntity : false,
28745
+ Name : "Gamma #1", // "side effect"
28746
+ _ : {
28747
+ DrillState : "leaf",
28748
+ NodeID : "2,false"
28749
+ }
28750
+ }, {
28751
+ "@odata.etag" : "etag1.3", // updated
28752
+ ArtistID : "1",
28753
+ IsActiveEntity : false,
28754
+ Name : "Beta #1", // "side effect"
28755
+ _ : {
28756
+ DrillState : "leaf",
28757
+ NodeID : "1,false"
28758
+ }
28759
+ }]
28760
+ })
28761
+ .expectChange("etag", [, "etag2.3", "etag1.3"])
28762
+ .expectChange("name", [, "Gamma #1", "Beta #1"]);
28763
+
28764
+ // code under test
28765
+ oRoot.expand();
28766
+
28767
+ return that.waitForChanges(assert, "expand root again");
28768
+ }).then(function () {
28769
+ checkTable("after expand root again", assert, oTable, [
28770
+ sFriend + "(ArtistID='0',IsActiveEntity=false)",
28771
+ sFriend + "(ArtistID='2',IsActiveEntity=false)",
28772
+ sFriend + "(ArtistID='1',IsActiveEntity=false)"
28773
+ ], [
28774
+ [undefined, true, 1, "etag0.1", "Alpha #1"],
28775
+ [undefined, undefined, 2, "etag2.3", "Gamma #1"],
28776
+ [undefined, undefined, 2, "etag1.3", "Beta #1"]
28777
+ ]);
28778
+ [, oGamma, oBeta] = oListBinding.getCurrentContexts();
28779
+
28780
+ assert.strictEqual(oGamma.getIndex(), 1);
28781
+ assert.deepEqual(oGamma.getObject(), {
28782
+ "@$ui5.node.level" : 2,
28783
+ "@odata.etag" : "etag2.3",
28784
+ ArtistID : "2",
28785
+ IsActiveEntity : false,
28786
+ Name : "Gamma #1",
28787
+ _ : {
28788
+ NodeID : "2,false"
28789
+ }
28790
+ });
28791
+ assert.strictEqual(oGamma.isTransient(), undefined, "persisted");
28792
+ assert.strictEqual(oGamma.created(), undefined);
28793
+
28794
+ assert.strictEqual(oBeta.getIndex(), 2);
28795
+ assert.deepEqual(oBeta.getObject(), {
28796
+ // "@$ui5.context.isTransient" deleted by #requestSideEffects/#expand
28797
+ "@$ui5.node.level" : 2,
28798
+ "@odata.etag" : "etag1.3",
28799
+ ArtistID : "1",
28800
+ IsActiveEntity : false,
28801
+ Name : "Beta #1",
28802
+ _ : {
28803
+ NodeID : "1,false"
28804
+ }
28805
+ });
28806
+ assert.strictEqual(oBeta.isTransient(), undefined, "persisted");
28807
+ assert.strictEqual(oBeta.created(), undefined);
28808
+
28809
+ return Promise.all([
28810
+ // code under test
28811
+ checkCanceled(assert, oGamma.move({parent : oBeta})),
28812
+ oModel.resetChanges()
28813
+ ]);
28814
+ }).then(function () {
28815
+ that.expectRequest({
28816
+ headers : {
28817
+ "If-Match" : "etag1.3",
28818
+ Prefer : "return=minimal"
28819
+ },
28820
+ method : "PATCH",
28821
+ url : "Artists(ArtistID='1',IsActiveEntity=false)",
28822
+ payload : {
28823
+ "BestFriend@odata.bind" : "Artists(ArtistID='2',IsActiveEntity=false)"
28824
+ }
28825
+ }, null, {ETag : "etag1.4"}) // 204 No Content
28826
+ .expectChange("etag", [,, "etag1.4"]);
28827
+
28828
+ return Promise.all([
28829
+ // code under test
28830
+ oBeta.move({parent : oGamma}), // Note: child's index does not change!
28831
+ that.waitForChanges(assert, "new parent already right before child")
28832
+ ]);
28833
+ }).then(function () {
28834
+ checkTable("after 'new parent already right before child'", assert, oTable, [
27635
28835
  sFriend + "(ArtistID='0',IsActiveEntity=false)",
27636
28836
  sFriend + "(ArtistID='2',IsActiveEntity=false)",
27637
28837
  sFriend + "(ArtistID='1',IsActiveEntity=false)"
27638
28838
  ], [
27639
- [true, 1, "Alpha"],
27640
- [undefined, 2, "Gamma: γ"],
27641
- [undefined, 2, "Beta: β"]
28839
+ [undefined, true, 1, "etag0.1", "Alpha #1"],
28840
+ [undefined, true, 2, "etag2.3", "Gamma #1"],
28841
+ [false, undefined, 3, "etag1.4", "Beta #1"]
27642
28842
  ]);
28843
+ const aCurrentContexts = oListBinding.getCurrentContexts();
28844
+ assert.strictEqual(oRoot, aCurrentContexts[0]);
28845
+ assert.strictEqual(oGamma, aCurrentContexts[1]);
28846
+ assert.strictEqual(oBeta, aCurrentContexts[2], "same instance");
28847
+
28848
+ assert.strictEqual(oGamma.getIndex(), 1);
28849
+ assert.deepEqual(oGamma.getObject(), {
28850
+ "@$ui5.node.isExpanded" : true,
28851
+ "@$ui5.node.level" : 2,
28852
+ "@odata.etag" : "etag2.3",
28853
+ ArtistID : "2",
28854
+ IsActiveEntity : false,
28855
+ Name : "Gamma #1",
28856
+ _ : {
28857
+ NodeID : "2,false"
28858
+ }
28859
+ });
28860
+ assert.strictEqual(oGamma.isTransient(), undefined, "persisted");
28861
+ assert.strictEqual(oGamma.created(), undefined);
28862
+
28863
+ assert.strictEqual(oBeta.getIndex(), 2); // unchanged by #move
28864
+ assert.deepEqual(oBeta.getObject(), {
28865
+ "@$ui5.context.isTransient" : false, // "moved"
28866
+ "@$ui5.node.level" : 3,
28867
+ "@odata.etag" : "etag1.4",
28868
+ ArtistID : "1",
28869
+ IsActiveEntity : false,
28870
+ Name : "Beta #1",
28871
+ _ : {
28872
+ NodeID : "1,false"
28873
+ }
28874
+ });
28875
+ assert.strictEqual(oBeta.isTransient(), false, "created persisted");
28876
+ assert.ok(oBeta.created() instanceof Promise);
28877
+
28878
+ return oBeta.created(); // to prove that it's not rejected
27643
28879
  });
27644
28880
  });
27645
28881
 
28882
+ //*********************************************************************************************
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.
28887
+ // JIRA: CPOUI5ODATAV4-2325
28888
+ [false, true].forEach((bMoveCollapsed) => {
28889
+ const sTitle = `Recursive Hierarchy: move node w/ children, collapsed=${bMoveCollapsed}`;
28890
+
28891
+ QUnit.test(sTitle, async function (assert) {
28892
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
28893
+ const sView = `
28894
+ <t:Table id="table" rows="{path : '/EMPLOYEES',
28895
+ parameters : {
28896
+ $$aggregation : {hierarchyQualifier : 'OrgChart'}
28897
+ }}" threshold="0" visibleRowCount="5">
28898
+ <Text text="{= %{@$ui5.node.isExpanded} }"/>
28899
+ <Text text="{= %{@$ui5.node.level} }"/>
28900
+ <Text id="id" text="{ID}"/>
28901
+ <Text text="{MANAGER_ID}"/>
28902
+ <Text text="{Name}"/>
28903
+ <Text text="{AGE}"/>
28904
+ </t:Table>`;
28905
+
28906
+ // 0 Alpha
28907
+ // 1 Beta
28908
+ // 1.1 Gamma
28909
+ // 1.2 Zeta
28910
+ // 2 Kappa
28911
+ // 3 Lambda
28912
+ // 9 Omega
28913
+ this.expectRequest("EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
28914
+ + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
28915
+ + ",NodeProperty='ID',Levels=1)"
28916
+ + "&$select=AGE,DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=5", {
28917
+ "@odata.count" : "2",
28918
+ value : [{
28919
+ AGE : 60,
28920
+ DrillState : "collapsed",
28921
+ ID : "0",
28922
+ MANAGER_ID : null,
28923
+ Name : "Alpha"
28924
+ }, {
28925
+ AGE : 69,
28926
+ DrillState : "leaf",
28927
+ ID : "9",
28928
+ MANAGER_ID : null,
28929
+ Name : "Omega"
28930
+ }]
28931
+ })
28932
+ .expectChange("id", ["0", "9"]);
28933
+
28934
+ await this.createView(assert, sView, oModel);
28935
+
28936
+ const oTable = this.oView.byId("table");
28937
+ checkTable("initial page", assert, oTable, [
28938
+ "/EMPLOYEES('0')",
28939
+ "/EMPLOYEES('9')"
28940
+ ], [
28941
+ [false, 1, "0", "", "Alpha", 60],
28942
+ [undefined, 1, "9", "", "Omega", 69],
28943
+ ["", "", "", "", "", ""],
28944
+ ["", "", "", "", "", ""],
28945
+ ["", "", "", "", "", ""]
28946
+ ]);
28947
+ const oAlpha = oTable.getRows()[0].getBindingContext();
28948
+ const oOmega = oTable.getRows()[1].getBindingContext();
28949
+
28950
+ this.expectRequest("EMPLOYEES?$apply=descendants($root/EMPLOYEES,OrgChart,ID"
28951
+ + ",filter(ID eq '0'),1)"
28952
+ + "&$select=AGE,DrillState,ID,MANAGER_ID,Name&$count=true&$skip=0&$top=5", {
28953
+ "@odata.count" : "3",
28954
+ value : [{
28955
+ AGE : 55,
28956
+ DrillState : "collapsed",
28957
+ ID : "1",
28958
+ MANAGER_ID : "0",
28959
+ Name : "Beta"
28960
+ }, {
28961
+ AGE : 56,
28962
+ DrillState : "leaf",
28963
+ ID : "2",
28964
+ MANAGER_ID : "0",
28965
+ Name : "Kappa"
28966
+ }, {
28967
+ AGE : 57,
28968
+ DrillState : "leaf",
28969
+ ID : "3",
28970
+ MANAGER_ID : "0",
28971
+ Name : "Lambda"
28972
+ }]
28973
+ })
28974
+ .expectChange("id", [, "1", "2", "3", "9"]);
28975
+
28976
+ oAlpha.expand();
28977
+
28978
+ await this.waitForChanges(assert, "expand 0 (Alpha)");
28979
+
28980
+ checkTable("after expand 0 (Alpha)", assert, oTable, [
28981
+ "/EMPLOYEES('0')",
28982
+ "/EMPLOYEES('1')",
28983
+ "/EMPLOYEES('2')",
28984
+ "/EMPLOYEES('3')",
28985
+ "/EMPLOYEES('9')"
28986
+ ], [
28987
+ [true, 1, "0", "", "Alpha", 60],
28988
+ [false, 2, "1", "0", "Beta", 55],
28989
+ [undefined, 2, "2", "0", "Kappa", 56],
28990
+ [undefined, 2, "3", "0", "Lambda", 57],
28991
+ [undefined, 1, "9", "", "Omega", 69]
28992
+ ]);
28993
+ const oBeta = oTable.getRows()[1].getBindingContext();
28994
+
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"]);
29014
+
29015
+ oBeta.expand();
29016
+
29017
+ await this.waitForChanges(assert, "expand 1 (Beta)");
29018
+
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
+ ]);
29034
+
29035
+ this.expectChange("id", [,, "2", "3", "9"]);
29036
+
29037
+ oBeta.collapse();
29038
+
29039
+ await this.waitForChanges(assert, "collapse 1 (Beta)");
29040
+
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
+ ]);
29054
+
29055
+ if (bMoveCollapsed) {
29056
+ this.expectChange("id", [, "9"]);
29057
+ oAlpha.collapse();
29058
+ }
29059
+
29060
+ this.expectEvents(assert, "sap.ui.model.odata.v4.ODataListBinding: /EMPLOYEES", [
29061
+ [, "change", {reason : "change"}]
29062
+ ])
29063
+ .expectRequest({
29064
+ headers : {
29065
+ Prefer : "return=minimal"
29066
+ },
29067
+ method : "PATCH",
29068
+ url : "EMPLOYEES('0')",
29069
+ payload : {
29070
+ "EMPLOYEE_2_MANAGER@odata.bind" : "EMPLOYEES('9')"
29071
+ }
29072
+ }) // 204 No Content
29073
+ .expectChange("id", bMoveCollapsed ? ["9", "0"] : ["9", "0", "1", "2", "3"]);
29074
+
29075
+ await Promise.all([
29076
+ oAlpha.move({parent : oOmega}),
29077
+ this.waitForChanges(assert, "move 0 (Alpha) to 9 (Omega)")
29078
+ ]);
29079
+
29080
+ if (bMoveCollapsed) {
29081
+ this.expectEvents(assert, "sap.ui.model.odata.v4.ODataListBinding: /EMPLOYEES", [
29082
+ [, "change", {reason : "change"}]
29083
+ ])
29084
+ .expectChange("id", [,, "1", "2", "3"]);
29085
+ oAlpha.expand();
29086
+
29087
+ await this.waitForChanges(assert, "expand 0 (Alpha)");
29088
+ }
29089
+
29090
+ checkTable("after move 0 (Alpha) to 9 (Omega)", assert, oTable, [
29091
+ "/EMPLOYEES('9')",
29092
+ "/EMPLOYEES('0')",
29093
+ "/EMPLOYEES('1')",
29094
+ "/EMPLOYEES('2')",
29095
+ "/EMPLOYEES('3')"
29096
+ ], [
29097
+ [true, 1, "9", "", "Omega", 69],
29098
+ [true, 2, "0", ""/*TODO "9"*/, "Alpha", 60],
29099
+ [false, 3, "1", "0", "Beta", 55],
29100
+ [undefined, 3, "2", "0", "Kappa", 56],
29101
+ [undefined, 3, "3", "0", "Lambda", 57]
29102
+ ]);
29103
+ });
29104
+ });
29105
+
29106
+ //*********************************************************************************************
29107
+ // Scenario: Show the single root node of a recursive hierarchy and expand it. Not all children
29108
+ // are loaded, but some placeholders remain. Create two new child nodes underneath the root.
29109
+ // Scroll down to load the other children.
29110
+ // JIRA: CPOUI5ODATAV4-2260
29111
+ //
29112
+ // Create new child and cancel immediately (JIRA: CPOUI5ODATAV4-2272)
29113
+ // Also delete instead of cancelling (JIRA: CPOUI5ODATAV4-2274)
29114
+ // Delete a created persisted child (JIRA: CPOUI5ODATAV4-2224)
29115
+ [false, true].forEach(function (bDelete) {
29116
+ const sTitle = `Recursive Hierarchy: create new children & placeholders, delete=${bDelete}`;
29117
+
29118
+ QUnit.test(sTitle, function (assert) {
29119
+ var oListBinding, oRoot, oTable;
29120
+
29121
+ const oModel = this.createSpecialCasesModel({autoExpandSelect : true});
29122
+ const sView = `
29123
+ <t:Table id="table" rows="{path : '/Artists',
29124
+ parameters : {
29125
+ $$aggregation : {
29126
+ hierarchyQualifier : 'OrgChart'
29127
+ }
29128
+ }}" threshold="0" visibleRowCount="3">
29129
+ <Text text="{= %{@$ui5.node.isExpanded} }"/>
29130
+ <Text text="{= %{@$ui5.node.level} }"/>
29131
+ <Text id="id" text="{ArtistID}"/>\
29132
+ <Text id="name" text="{Name}"/>
29133
+ </t:Table>`;
29134
+ const that = this;
29135
+
29136
+ this.expectRequest({
29137
+ batchNo : 1,
29138
+ url : "Artists?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
29139
+ + "HierarchyNodes=$root/Artists,HierarchyQualifier='OrgChart'"
29140
+ + ",NodeProperty='_/NodeID',Levels=1)"
29141
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID"
29142
+ + "&$count=true&$skip=0&$top=3"
29143
+ }, {
29144
+ "@odata.count" : "1",
29145
+ value : [{
29146
+ ArtistID : "0",
29147
+ IsActiveEntity : false,
29148
+ Name : "Alpha",
29149
+ _ : {
29150
+ // DescendantCount : "0", // not needed w/o expandTo
29151
+ // DistanceFromRoot : "0", // not needed w/o expandTo
29152
+ DrillState : "collapsed",
29153
+ NodeID : "0,false"
29154
+ }
29155
+ }]
29156
+ })
29157
+ .expectChange("id", ["0"])
29158
+ .expectChange("name", ["Alpha"]);
29159
+
29160
+ return this.createView(assert, sView, oModel).then(function () {
29161
+ oTable = that.oView.byId("table");
29162
+ oRoot = oTable.getRows()[0].getBindingContext();
29163
+ oListBinding = oRoot.getBinding();
29164
+
29165
+ checkTable("root is leaf", assert, oTable, [
29166
+ "/Artists(ArtistID='0',IsActiveEntity=false)"
29167
+ ], [
29168
+ [false, 1, "0", "Alpha"],
29169
+ ["", "", "", ""],
29170
+ ["", "", "", ""]
29171
+ ]);
29172
+
29173
+ that.expectRequest("Artists?$apply=descendants($root/Artists,OrgChart,_/NodeID"
29174
+ + ",filter(ArtistID eq '0' and IsActiveEntity eq false),1)"
29175
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID"
29176
+ + "&$count=true&$skip=0&$top=3", {
29177
+ "@odata.count" : "5",
29178
+ value : [{
29179
+ ArtistID : "1",
29180
+ IsActiveEntity : false,
29181
+ Name : "Beta",
29182
+ _ : {
29183
+ DrillState : "leaf",
29184
+ NodeID : "1,false"
29185
+ }
29186
+ }, {
29187
+ ArtistID : "2",
29188
+ IsActiveEntity : false,
29189
+ Name : "Gamma",
29190
+ _ : {
29191
+ DrillState : "leaf",
29192
+ NodeID : "2,false"
29193
+ }
29194
+ }, {
29195
+ ArtistID : "3",
29196
+ IsActiveEntity : false,
29197
+ Name : "Delta",
29198
+ _ : {
29199
+ DrillState : "leaf",
29200
+ NodeID : "3,false"
29201
+ }
29202
+ }]
29203
+ })
29204
+ .expectChange("id", [, "1", "2"])
29205
+ .expectChange("name", [, "Beta", "Gamma"]);
29206
+
29207
+ // code under test
29208
+ oRoot.expand();
29209
+
29210
+ return that.waitForChanges(assert, "expand");
29211
+ }).then(function () {
29212
+ checkTable("after expand", assert, oTable, [
29213
+ "/Artists(ArtistID='0',IsActiveEntity=false)",
29214
+ "/Artists(ArtistID='1',IsActiveEntity=false)",
29215
+ "/Artists(ArtistID='2',IsActiveEntity=false)",
29216
+ "/Artists(ArtistID='3',IsActiveEntity=false)"
29217
+ ], [
29218
+ [true, 1, "0", "Alpha"],
29219
+ [undefined, 2, "1", "Beta"],
29220
+ [undefined, 2, "2", "Gamma"]
29221
+ ], 6);
29222
+
29223
+ // code under test (JIRA: CPOUI5ODATAV4-2272, JIRA: CPOUI5ODATAV4-2274)
29224
+ const oLostChild = oListBinding.create({
29225
+ "@$ui5.node.parent" : oRoot,
29226
+ Name : "n/a"
29227
+ }, /*bSkipRefresh*/true);
29228
+ if (bDelete) {
29229
+ oLostChild.delete();
29230
+ } else {
29231
+ oModel.resetChanges();
29232
+ }
29233
+
29234
+ that.expectChange("id", [, "", "1"])
29235
+ .expectChange("name", [, "1st new child", "Beta"])
29236
+ .expectRequest({
29237
+ method : "POST",
29238
+ url : "Artists",
29239
+ payload : {
29240
+ "BestFriend@odata.bind" : "Artists(ArtistID='0',IsActiveEntity=false)",
29241
+ Name : "1st new child"
29242
+ }
29243
+ }, {
29244
+ ArtistID : "11",
29245
+ IsActiveEntity : false,
29246
+ Name : "First new child" // side effect
29247
+ })
29248
+ .expectChange("id", [, "11"])
29249
+ .expectChange("name", [, "First new child"]);
29250
+
29251
+ // code under test
29252
+ const oChild = oListBinding.create({
29253
+ "@$ui5.node.parent" : oRoot,
29254
+ Name : "1st new child"
29255
+ }, /*bSkipRefresh*/true);
29256
+
29257
+ return Promise.all([
29258
+ checkCanceled(assert, oLostChild.created()),
29259
+ oChild.created(),
29260
+ that.waitForChanges(assert, "create 1st child")
29261
+ ]);
29262
+ }).then(function () {
29263
+ that.expectChange("id", [, "", "11"])
29264
+ .expectChange("name", [, "2nd new child", "First new child"])
29265
+ .expectRequest({
29266
+ method : "POST",
29267
+ url : "Artists",
29268
+ payload : {
29269
+ "BestFriend@odata.bind" : "Artists(ArtistID='0',IsActiveEntity=false)",
29270
+ Name : "2nd new child"
29271
+ }
29272
+ }, {
29273
+ "@odata.etag" : "etag2.0",
29274
+ ArtistID : "12",
29275
+ IsActiveEntity : false,
29276
+ Name : "Second new child" // side effect
29277
+ })
29278
+ .expectChange("id", [, "12"])
29279
+ .expectChange("name", [, "Second new child"]);
29280
+
29281
+ // code under test
29282
+ const oChild = oListBinding.create({
29283
+ "@$ui5.node.parent" : oRoot,
29284
+ Name : "2nd new child"
29285
+ }, /*bSkipRefresh*/true);
29286
+
29287
+ return Promise.all([
29288
+ oChild.created(),
29289
+ that.waitForChanges(assert, "create 2nd child")
29290
+ ]);
29291
+ }).then(function () {
29292
+ checkTable("after creation", assert, oTable, [
29293
+ "/Artists(ArtistID='0',IsActiveEntity=false)",
29294
+ "/Artists(ArtistID='12',IsActiveEntity=false)",
29295
+ "/Artists(ArtistID='11',IsActiveEntity=false)",
29296
+ "/Artists(ArtistID='1',IsActiveEntity=false)",
29297
+ "/Artists(ArtistID='2',IsActiveEntity=false)",
29298
+ "/Artists(ArtistID='3',IsActiveEntity=false)"
29299
+ ], [
29300
+ [true, 1, "0", "Alpha"],
29301
+ [undefined, 2, "12", "Second new child"],
29302
+ [undefined, 2, "11", "First new child"]
29303
+ ], 8);
29304
+
29305
+ that.expectChange("id", [,,, "1", "2", "3"])
29306
+ .expectChange("name", [,,, "Beta", "Gamma", "Delta"]);
29307
+
29308
+ // code under test
29309
+ oTable.setFirstVisibleRow(3);
29310
+
29311
+ return that.waitForChanges(assert, "scroll down");
29312
+ }).then(function () {
29313
+ checkTable("after scroll down", assert, oTable, [
29314
+ "/Artists(ArtistID='0',IsActiveEntity=false)",
29315
+ "/Artists(ArtistID='12',IsActiveEntity=false)",
29316
+ "/Artists(ArtistID='11',IsActiveEntity=false)",
29317
+ "/Artists(ArtistID='1',IsActiveEntity=false)",
29318
+ "/Artists(ArtistID='2',IsActiveEntity=false)",
29319
+ "/Artists(ArtistID='3',IsActiveEntity=false)"
29320
+ ], [
29321
+ [undefined, 2, "1", "Beta"],
29322
+ [undefined, 2, "2", "Gamma"],
29323
+ [undefined, 2, "3", "Delta"]
29324
+ ], 8);
29325
+
29326
+ that.expectRequest("Artists?$apply=descendants($root/Artists,OrgChart,_/NodeID"
29327
+ + ",filter(ArtistID eq '0' and IsActiveEntity eq false),1)"
29328
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID"
29329
+ + "&$filter=not (ArtistID eq '11' and IsActiveEntity eq false"
29330
+ + " or ArtistID eq '12' and IsActiveEntity eq false)"
29331
+ + "&$skip=3&$top=2", {
29332
+ value : [{
29333
+ ArtistID : "4",
29334
+ IsActiveEntity : false,
29335
+ Name : "Epsilon",
29336
+ _ : {
29337
+ DrillState : "leaf",
29338
+ NodeID : "4,false"
29339
+ }
29340
+ }, {
29341
+ ArtistID : "5",
29342
+ IsActiveEntity : false,
29343
+ Name : "Zeta",
29344
+ _ : {
29345
+ DrillState : "leaf",
29346
+ NodeID : "5,false"
29347
+ }
29348
+ }]
29349
+ })
29350
+ .expectChange("id", [,,,,, "3", "4", "5"])
29351
+ .expectChange("name", [,,,,, "Delta", "Epsilon", "Zeta"]);
29352
+
29353
+ // code under test
29354
+ oTable.setFirstVisibleRow(5);
29355
+
29356
+ return that.waitForChanges(assert, "scroll to bottom");
29357
+ }).then(function () {
29358
+ checkTable("after scroll to bottom", assert, oTable, [
29359
+ "/Artists(ArtistID='0',IsActiveEntity=false)",
29360
+ "/Artists(ArtistID='12',IsActiveEntity=false)",
29361
+ "/Artists(ArtistID='11',IsActiveEntity=false)",
29362
+ "/Artists(ArtistID='1',IsActiveEntity=false)",
29363
+ "/Artists(ArtistID='2',IsActiveEntity=false)",
29364
+ "/Artists(ArtistID='3',IsActiveEntity=false)",
29365
+ "/Artists(ArtistID='4',IsActiveEntity=false)",
29366
+ "/Artists(ArtistID='5',IsActiveEntity=false)"
29367
+ ], [
29368
+ [undefined, 2, "3", "Delta"],
29369
+ [undefined, 2, "4", "Epsilon"],
29370
+ [undefined, 2, "5", "Zeta"]
29371
+ ]);
29372
+ }).then(function () {
29373
+ that.expectChange("id", ["0", "12", "11"])
29374
+ .expectChange("name", ["Alpha", "Second new child", "First new child"]);
29375
+
29376
+ oTable.setFirstVisibleRow(0);
29377
+
29378
+ return that.waitForChanges(assert, "scroll to top");
29379
+ }).then(function () {
29380
+ const oCreatedPersisted = oTable.getRows()[1].getBindingContext();
29381
+ assert.strictEqual(oCreatedPersisted.isTransient(), false);
29382
+
29383
+ that.expectChange("id", [, "11", "1"])
29384
+ .expectChange("name", [, "First new child", "Beta"])
29385
+ .expectRequest({
29386
+ method : "DELETE",
29387
+ headers : {
29388
+ "If-Match" : "etag2.0"
29389
+ },
29390
+ url : "Artists(ArtistID='12',IsActiveEntity=false)"
29391
+ });
29392
+
29393
+ return Promise.all([
29394
+ // code under test (JIRA: CPOUI5ODATAV4-2224)
29395
+ oCreatedPersisted.delete(),
29396
+ that.waitForChanges(assert, "delete created persisted child")
29397
+ ]);
29398
+ }).then(function () {
29399
+ checkTable("after deletion of created persisted", assert, oTable, [
29400
+ "/Artists(ArtistID='0',IsActiveEntity=false)",
29401
+ "/Artists(ArtistID='11',IsActiveEntity=false)",
29402
+ "/Artists(ArtistID='1',IsActiveEntity=false)",
29403
+ "/Artists(ArtistID='2',IsActiveEntity=false)",
29404
+ "/Artists(ArtistID='3',IsActiveEntity=false)",
29405
+ "/Artists(ArtistID='4',IsActiveEntity=false)",
29406
+ "/Artists(ArtistID='5',IsActiveEntity=false)"
29407
+ ], [
29408
+ [true, 1, "0", "Alpha"],
29409
+ [undefined, 2, "11", "First new child"],
29410
+ [undefined, 2, "1", "Beta"]
29411
+ ]);
29412
+ });
29413
+ });
29414
+ });
29415
+
27646
29416
  //*********************************************************************************************
27647
29417
  // Scenario: Application tries to overwrite client-side instance annotations.
27648
29418
  // JIRA: CPOUI5UISERVICESV3-1220
@@ -28182,7 +29952,8 @@ sap.ui.define([
28182
29952
  // properly computed.
28183
29953
  // BCP 1870081505
28184
29954
  QUnit.test("bindElement called twice on table", function (assert) {
28185
- var oModel = this.createTeaBusiModel({autoExpandSelect : true}),
29955
+ var fnRespond,
29956
+ oModel = this.createTeaBusiModel({autoExpandSelect : true}),
28186
29957
  oTable,
28187
29958
  // Note: table must be "growing" otherwise it does not use ECD
28188
29959
  sView = '\
@@ -28214,24 +29985,88 @@ sap.ui.define([
28214
29985
  return that.waitForChanges(assert);
28215
29986
  }).then(function () {
28216
29987
  that.expectRequest("TEAMS('TEAM_01')?$select=Team_Id"
28217
- + "&$expand=TEAM_2_EMPLOYEES($select=ID,Name)", {
28218
- Team_Id : "TEAM_01",
28219
- TEAM_2_EMPLOYEES : [{
28220
- ID : "3",
28221
- Name : "Jonathan Smith"
28222
- }]
28223
- })
28224
- .expectChange("name", ["Jonathan Smith"]);
29988
+ + "&$expand=TEAM_2_EMPLOYEES($select=ID,Name)", new Promise(function (resolve) {
29989
+ fnRespond = resolve.bind(null, {
29990
+ Team_Id : "TEAM_01",
29991
+ TEAM_2_EMPLOYEES : [{
29992
+ ID : "3",
29993
+ Name : "Jonathan Smith"
29994
+ }]
29995
+ });
29996
+ }));
28225
29997
 
28226
29998
  // code under test
28227
29999
  oTable.bindElement("/TEAMS('TEAM_01')");
28228
30000
 
28229
- return that.waitForChanges(assert);
30001
+ return that.waitForChanges(assert, "request");
28230
30002
  }).then(function () {
28231
- assert.strictEqual(oTable.getItems().length, 1, "The one entry is still displayed");
30003
+ assert.strictEqual(oTable.getItems().length, 0, "All gone");
30004
+
30005
+ that.expectChange("name", ["Jonathan Smith"]);
30006
+
30007
+ fnRespond();
30008
+
30009
+ return that.waitForChanges(assert, "response");
30010
+ }).then(function () {
30011
+ assert.strictEqual(oTable.getItems().length, 1, "The one entry is displayed again");
28232
30012
  });
28233
30013
  });
28234
30014
 
30015
+ //*********************************************************************************************
30016
+ // Scenario: ManagedObject#setParent is called on a table to remove and add a parent. This
30017
+ // causes the list binding to be recreated. No diff must be used in order to avoid duplicate
30018
+ // data.
30019
+ // BCP: 2380130744
30020
+ QUnit.test("BCP: 2380130744", async function (assert) {
30021
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
30022
+ // Note: table must be "growing" otherwise it does not use ECD
30023
+ const sView = `
30024
+ <FlexBox id="form">
30025
+ <Table id="table" items="{/EMPLOYEES}" growing="true">
30026
+ <Text id="name" text="{Name}"/>
30027
+ </Table>
30028
+ </FlexBox>`;
30029
+
30030
+ this.expectRequest("EMPLOYEES?$select=ID,Name&$skip=0&$top=20", {
30031
+ value : [{
30032
+ ID : "3",
30033
+ Name : "Jonathan Smith"
30034
+ }]
30035
+ })
30036
+ .expectChange("name", ["Jonathan Smith"]);
30037
+
30038
+ await this.createView(assert, sView, oModel);
30039
+
30040
+ const oTable = this.oView.byId("table");
30041
+
30042
+ // code under test
30043
+ oTable.setParent(null);
30044
+
30045
+ await this.waitForChanges(assert, "remove parent");
30046
+
30047
+ assert.strictEqual(oTable.getBinding("items"), undefined);
30048
+ assert.strictEqual(oTable.getItems().length, 1);
30049
+ assert.strictEqual(oTable.getItems()[0].getCells()[0].getText(), "Jonathan Smith",
30050
+ "still there!");
30051
+
30052
+ this.expectRequest("EMPLOYEES?$select=ID,Name&$skip=0&$top=20", {
30053
+ value : [{
30054
+ ID : "2",
30055
+ Name : "Frederic Fall"
30056
+ }]
30057
+ })
30058
+ .expectChange("name", ["Frederic Fall"]);
30059
+
30060
+ // code under test
30061
+ oTable.setParent(this.oView.byId("form"));
30062
+
30063
+ await this.waitForChanges(assert, "restore parent");
30064
+
30065
+ checkTable("after restore parent", assert, oTable, ["/EMPLOYEES('2')"], [
30066
+ ["Frederic Fall"]
30067
+ ]);
30068
+ });
30069
+
28235
30070
  //*********************************************************************************************
28236
30071
  // Scenario: Update a property via a control and check that the control contains the value
28237
30072
  // afterwards. Reason: ManagedObject#updateModelProperty fetches the updated model value and
@@ -28895,8 +30730,6 @@ sap.ui.define([
28895
30730
 
28896
30731
  return that.waitForChanges(assert);
28897
30732
  }).then(function () {
28898
- var oMessageManager = sap.ui.getCore().getMessageManager();
28899
-
28900
30733
  // 4c. Patching a property via the wrong context must not succeed
28901
30734
  // We're not interested in the exact errors, only in some failure
28902
30735
  that.oLogMock.expects("error").twice();
@@ -28905,8 +30738,8 @@ sap.ui.define([
28905
30738
  .setProperty("BestFriend/Name", "n/a")
28906
30739
  .then(mustFail(assert), function () {
28907
30740
  // expect one message and remove it again
28908
- assert.strictEqual(oMessageManager.getMessageModel().getObject("/").length, 1);
28909
- oMessageManager.removeAllMessages();
30741
+ assert.strictEqual(Messaging.getMessageModel().getObject("/").length, 1);
30742
+ Messaging.removeAllMessages();
28910
30743
 
28911
30744
  assert.strictEqual(oReturnValueContext.getProperty("BestFriend/Name"),
28912
30745
  "Sgt. Pepper (modified)");
@@ -30538,17 +32371,32 @@ sap.ui.define([
30538
32371
  payload : {}
30539
32372
  }, {
30540
32373
  ArtistID : "2",
30541
- IsActiveEntity : false
30542
- });
32374
+ IsActiveEntity : false,
32375
+ Messages : [{
32376
+ message : "Some Message",
32377
+ numericSeverity : 3,
32378
+ target : "ArtistID",
32379
+ transition : false
32380
+ }]
32381
+ })
32382
+ .expectMessages([{
32383
+ message : "Some Message",
32384
+ targets : [
32385
+ "/Artists(ArtistID='1',IsActiveEntity=true)/BestFriend/" + sAction
32386
+ + "(...)/ArtistID"
32387
+ ],
32388
+ type : "Warning"
32389
+ }]);
30543
32390
 
30544
32391
  return Promise.all([
30545
32392
  that.oView.byId("action").getObjectBinding().execute(),
30546
32393
  that.waitForChanges(assert)
30547
32394
  ]);
30548
- }).then(function () {
32395
+ }).then(function ([oReturnValueContext]) {
30549
32396
  // TODO return value context not supported here
30550
32397
  // assert.strictEqual(aResults[0].getPath(),
30551
32398
  // "Artists(ArtistID='2',IsActiveEntity=false)");
32399
+ assert.strictEqual(oReturnValueContext, undefined);
30552
32400
  });
30553
32401
  });
30554
32402
 
@@ -30608,9 +32456,13 @@ sap.ui.define([
30608
32456
  });
30609
32457
 
30610
32458
  //*********************************************************************************************
30611
- // Scenario: Create entity for a relative ListBinding, save the new entity and call action
30612
- // import for the new non-transient entity
32459
+ // Scenario: Create entity for a relative ListBinding, save the new entity and call a bound
32460
+ // action for the new non-transient entity
30613
32461
  // JIRA: CPOUI5UISERVICESV3-1233
32462
+ //
32463
+ // Ensure that a Return Value Context is created and the structure of the path is same like the
32464
+ // binding parameter
32465
+ // JIRA: CPOUI5ODATAV4-2096
30614
32466
  QUnit.test("Create relative, save and call action", function (assert) {
30615
32467
  var oCreatedContext,
30616
32468
  oModel = this.createTeaBusiModel(),
@@ -30653,15 +32505,24 @@ sap.ui.define([
30653
32505
  that.expectRequest({
30654
32506
  method : "POST",
30655
32507
  url : "TEAMS('42')/TEAM_2_EMPLOYEES('7')/"
30656
- + "com.sap.gateway.default.iwbep.tea_busi.v0001.AcChangeTeamOfEmployee",
30657
- payload : {TeamID : "TEAM_02"}
30658
- }, {ID : "7"});
30659
- oAction.setParameter("TeamID", "TEAM_02");
32508
+ + "com.sap.gateway.default.iwbep.tea_busi.v0001.AcChangeTeamOfEmployee"
32509
+ + "?$expand=EMPLOYEE_2_TEAM($select=Team_Id)",
32510
+ payload : {TeamID : "02"}
32511
+ }, {
32512
+ EMPLOYEE_2_TEAM : {
32513
+ Team_Id : "02"
32514
+ },
32515
+ ID : "7"
32516
+ });
32517
+ oAction.setParameter("TeamID", "02");
30660
32518
 
30661
32519
  return Promise.all([
30662
32520
  // code under test
30663
- oAction.execute(),
30664
- // Note: no R.V.C. because path "/TEAMS('42')/TEAM_2_EMPLOYEES('7')" too long
32521
+ oAction.execute().then(function (oReturnValueContext) {
32522
+ assert.strictEqual(
32523
+ oReturnValueContext.getPath(),
32524
+ "/TEAMS('02')/TEAM_2_EMPLOYEES('7')");
32525
+ }),
30665
32526
  that.waitForChanges(assert)
30666
32527
  ]);
30667
32528
  });
@@ -32161,7 +34022,7 @@ sap.ui.define([
32161
34022
  ]);
32162
34023
  }).then(function () {
32163
34024
  // remove persistent, technical messages from above
32164
- sap.ui.getCore().getMessageManager().removeAllMessages();
34025
+ Messaging.removeAllMessages();
32165
34026
 
32166
34027
  that.expectMessages([]);
32167
34028
 
@@ -34942,7 +36803,7 @@ sap.ui.define([
34942
36803
  type : "Error"
34943
36804
  }]);
34944
36805
 
34945
- sap.ui.getCore().getMessageManager().removeAllMessages();
36806
+ Messaging.removeAllMessages();
34946
36807
 
34947
36808
  return Promise.all([
34948
36809
  // code under test
@@ -34975,7 +36836,7 @@ sap.ui.define([
34975
36836
  type : "Warning"
34976
36837
  }]);
34977
36838
 
34978
- sap.ui.getCore().getMessageManager().removeAllMessages();
36839
+ Messaging.removeAllMessages();
34979
36840
 
34980
36841
  // code under test
34981
36842
  oTable.getItems("items")[0].getCells()[1].getBinding("value")
@@ -37028,6 +38889,102 @@ sap.ui.define([
37028
38889
  });
37029
38890
  });
37030
38891
 
38892
+ //*********************************************************************************************
38893
+ // Scenario: Execute a bound action, this returns a return value context although the path
38894
+ // contains navigation properties.
38895
+ // JIRA: CPOUI5ODATAV4-2096
38896
+ [false, true].forEach(function (bInheritExpandSelect) {
38897
+ ["TEAM_01", "TEAM_02"].forEach(function (sTeamId) {
38898
+ ["1", "2"].forEach(function (sEmployeeId) {
38899
+ var sTitle = "CPOUI5ODATAV4-2096 - Bound Action with RVC, Team changed: "
38900
+ + (sTeamId === "TEAM_02") + ", EmployeeId changed: " + (sEmployeeId === "2")
38901
+ + ", bInheritExpandSelect: " + bInheritExpandSelect;
38902
+
38903
+ QUnit.test(sTitle, async function (assert) {
38904
+ var sChangeTeamAction
38905
+ = "com.sap.gateway.default.iwbep.tea_busi.v0001.AcChangeTeamOfEmployee",
38906
+ oModel = this.createTeaBusiModel({autoExpandSelect : true}),
38907
+ sRVCPath = "/TEAMS('" + sTeamId + "')/TEAM_2_EMPLOYEES('" + sEmployeeId + "')",
38908
+ sView = '\
38909
+ <Table id="teams" items="{path : \'/TEAMS\'}">\
38910
+ <Text id="teamId" text="{Team_Id}"/>\
38911
+ </Table>\
38912
+ <Table id="employees" items="{path : \'TEAM_2_EMPLOYEES\', parameters : {$$ownRequest : true}}">\
38913
+ <Input id="name" value="{Name}"/>\
38914
+ <Text id="team" text="{TEAM_ID}"/>\
38915
+ </Table>';
38916
+
38917
+ this.expectRequest("TEAMS?$select=Team_Id&$skip=0&$top=100", {
38918
+ value : [{Team_Id : "TEAM_01"}, {Team_Id : "TEAM_02"}]
38919
+ })
38920
+ .expectChange("teamId", ["TEAM_01", "TEAM_02"])
38921
+ .expectChange("name", [])
38922
+ .expectChange("team", []);
38923
+
38924
+ await this.createView(assert, sView, oModel);
38925
+
38926
+ this.expectRequest("TEAMS('TEAM_01')/TEAM_2_EMPLOYEES?$select=ID,Name,TEAM_ID"
38927
+ + "&$skip=0&$top=100", {
38928
+ value : [{ID : "1", Name : "Jonathan Smith", TEAM_ID : "TEAM_01"}]
38929
+ })
38930
+ .expectChange("name", ["Jonathan Smith"])
38931
+ .expectChange("team", ["TEAM_01"]);
38932
+
38933
+ this.oView.byId("employees").setBindingContext(
38934
+ this.oView.byId("teams").getBinding("items").getCurrentContexts()[0]);
38935
+
38936
+ await this.waitForChanges(assert);
38937
+
38938
+ const oResponse = {
38939
+ Age : "42",
38940
+ EMPLOYEE_2_TEAM : {
38941
+ Team_Id : sTeamId
38942
+ },
38943
+ ID : sEmployeeId
38944
+ };
38945
+
38946
+ if (bInheritExpandSelect) {
38947
+ oResponse["Name"] = "Jonathan Smith";
38948
+ oResponse["TEAM_ID"] = sTeamId;
38949
+ }
38950
+
38951
+ const oEmployeesBinding = this.oView.byId("employees").getBinding("items");
38952
+ const oEmployeeContext = oEmployeesBinding.getCurrentContexts()[0];
38953
+ const oActionBinding = this.oModel.bindContext(sChangeTeamAction + "(...)",
38954
+ oEmployeeContext, {
38955
+ $select : ["Age"],
38956
+ $$inheritExpandSelect : bInheritExpandSelect
38957
+ });
38958
+
38959
+ this.expectRequest({
38960
+ method : "POST",
38961
+ payload : {
38962
+ TeamID : sTeamId
38963
+ },
38964
+ url : "TEAMS('TEAM_01')/TEAM_2_EMPLOYEES('1')" + "/" + sChangeTeamAction
38965
+ + (bInheritExpandSelect
38966
+ ? "?$select=Age,ID,Name,TEAM_ID"
38967
+ : "?$select=Age,ID")
38968
+ + "&$expand=EMPLOYEE_2_TEAM($select=Team_Id)"
38969
+ }, oResponse);
38970
+
38971
+ if (sTeamId === "TEAM_02" && sEmployeeId === "1" && bInheritExpandSelect) {
38972
+ this.expectChange("team", ["TEAM_02"]);
38973
+ }
38974
+
38975
+ const [oReturnValueContext] = await Promise.all([
38976
+ oActionBinding
38977
+ .setParameter("TeamID", sTeamId)
38978
+ .execute(),
38979
+ this.waitForChanges(assert)
38980
+ ]);
38981
+
38982
+ assert.strictEqual(oReturnValueContext.getPath(), sRVCPath);
38983
+ });
38984
+ });
38985
+ });
38986
+ });
38987
+
37031
38988
  //*********************************************************************************************
37032
38989
  // Scenario: Delete an entity via the model. This must not stumble over bindings below a not-yet
37033
38990
  // destroyed context of an ODLB which is already unresolved (kept in mPreviousContextsByPath),
@@ -37446,6 +39403,40 @@ sap.ui.define([
37446
39403
  return this.createView(assert, sView, oModel);
37447
39404
  });
37448
39405
 
39406
+ //*********************************************************************************************
39407
+ // Scenario: Path reduction and change listener
39408
+ // "defaultChannel" has a reducible path. See that it is properly deregistered with the delete,
39409
+ // so that the refresh promise resolves.
39410
+ // BCP: 2370061110
39411
+ QUnit.test("BCP: 2370061110", async function (assert) {
39412
+ const oModel = this.createSpecialCasesModel({autoExpandSelect : true});
39413
+ const sView = `
39414
+ <FlexBox id="form" binding="{/Artists(ArtistID='1',IsActiveEntity=false)}">
39415
+ <Text id="defaultChannel" text="{_Publication/_Artist/defaultChannel}"/>
39416
+ </FlexBox>`;
39417
+
39418
+ this.expectRequest("Artists(ArtistID='1',IsActiveEntity=false)"
39419
+ + "?$select=ArtistID,IsActiveEntity,defaultChannel", {
39420
+ ArtistID : "1",
39421
+ IsActiveEntity : false,
39422
+ defaultChannel : "test"
39423
+ })
39424
+ .expectChange("defaultChannel", "test");
39425
+
39426
+ await this.createView(assert, sView, oModel);
39427
+
39428
+ this.expectChange("defaultChannel", null)
39429
+ .expectRequest("DELETE Artists(ArtistID='1',IsActiveEntity=false)");
39430
+
39431
+ const oContext = this.oView.byId("form").getBindingContext();
39432
+
39433
+ await Promise.all([
39434
+ oContext.delete(),
39435
+ oContext.getBinding().requestRefresh(),
39436
+ this.waitForChanges(assert, "delete")
39437
+ ]);
39438
+ });
39439
+
37449
39440
  //*********************************************************************************************
37450
39441
  // Scenario: Operation on reduceable path. The operation path will not be reduced, but the
37451
39442
  // reduced path must be used to access the binding parameter.
@@ -38355,7 +40346,7 @@ sap.ui.define([
38355
40346
  assert.equal(oTableBinding.getLength(), 3);
38356
40347
 
38357
40348
  // remove persistent, technical messages from above
38358
- sap.ui.getCore().getMessageManager().removeAllMessages();
40349
+ Messaging.removeAllMessages();
38359
40350
  that.expectMessages([]);
38360
40351
 
38361
40352
  oCausingError = oFixture.expectations.call(that);
@@ -38459,7 +40450,7 @@ sap.ui.define([
38459
40450
  var oError = createErrorInsideBatch();
38460
40451
 
38461
40452
  // remove persistent, technical messages from above
38462
- sap.ui.getCore().getMessageManager().removeAllMessages();
40453
+ Messaging.removeAllMessages();
38463
40454
 
38464
40455
  that.oLogMock.expects("error")
38465
40456
  .withExactArgs("POST on 'SalesOrderList' failed; will be repeated automatically",
@@ -41497,7 +43488,7 @@ sap.ui.define([
41497
43488
  type : "Success"
41498
43489
  }]);
41499
43490
 
41500
- sap.ui.getCore().getMessageManager().removeAllMessages();
43491
+ Messaging.removeAllMessages();
41501
43492
  oInput.getBinding("value").setValue("F3");
41502
43493
 
41503
43494
  return Promise.all([
@@ -46792,6 +48783,54 @@ sap.ui.define([
46792
48783
  });
46793
48784
  });
46794
48785
 
48786
+ //*********************************************************************************************
48787
+ // Scenario: Refresh a binding with $$sharedRequest while a read request is pending.
48788
+ // BCP: 2370078660
48789
+ QUnit.test("BCP: 2370078660", async function (assert) {
48790
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true, sharedRequests : true});
48791
+ const sView = `
48792
+ <Table id="table" items="{path : '/TEAMS', suspended : true}">
48793
+ <Text id="name" text="{Name}"/>
48794
+ </Table>`;
48795
+
48796
+ this.expectChange("name", []);
48797
+
48798
+ await this.createView(assert, sView, oModel);
48799
+
48800
+ let fnResolve;
48801
+ const oResponsePromise = new Promise((resolve) => { fnResolve = resolve; });
48802
+ this.expectRequest("TEAMS?$select=Name,Team_Id&$skip=0&$top=100", oResponsePromise);
48803
+
48804
+ const oBinding = this.oView.byId("table").getBinding("items");
48805
+ oBinding.resume();
48806
+
48807
+ await this.waitForChanges(assert, "resume");
48808
+
48809
+ this.expectCanceledError(
48810
+ "Failed to get contexts for /sap/opu/odata4/IWBEP/TEA/default/IWBEP/TEA_BUSI/0001"
48811
+ + "/TEAMS with start index 0 and length 100",
48812
+ "Request is obsolete")
48813
+ .expectCanceledError(
48814
+ "Failed to get contexts for /sap/opu/odata4/IWBEP/TEA/default/IWBEP/TEA_BUSI/0001"
48815
+ + "/TEAMS with start index 0 and length 100",
48816
+ "Request is obsolete")
48817
+ .expectRequest("TEAMS?$select=Name,Team_Id&$skip=0&$top=100", {
48818
+ value : [
48819
+ {Team_Id : "1", Name : "Team #1"},
48820
+ {Team_Id : "2", Name : "Team #2"}
48821
+ ]
48822
+ })
48823
+ .expectChange("name", ["Team #1", "Team #2"]);
48824
+
48825
+ const oRefreshPromise = oBinding.requestRefresh();
48826
+ fnResolve(); // no need to give a result; it will be obsoleted anyway
48827
+
48828
+ await Promise.all([
48829
+ oRefreshPromise,
48830
+ this.waitForChanges(assert, "refresh while resume request is pending")
48831
+ ]);
48832
+ });
48833
+
46795
48834
  //*********************************************************************************************
46796
48835
  // Scenario: Absolute property bindings for $count
46797
48836
  // 1. Refresh a simple absolute property binding for $count.
@@ -47365,6 +49404,14 @@ sap.ui.define([
47365
49404
  assert.strictEqual(oBinding.hasPendingChanges(true), false);
47366
49405
  oBinding.filter(new Filter("MANAGER_ID", FilterOperator.NE, 666));
47367
49406
 
49407
+ // code under test BCP: 2380097809
49408
+ const aContexts = oBinding.getAllCurrentContexts();
49409
+
49410
+ assert.strictEqual(aContexts.length, 3);
49411
+ assert.strictEqual(aContexts[0], oContextC);
49412
+ assert.strictEqual(aContexts[1], oContextB);
49413
+ assert.strictEqual(aContexts[2], oContextA);
49414
+
47368
49415
  return that.waitForChanges(assert, "filter");
47369
49416
  }).then(function () {
47370
49417
  that.expectRequest("TEAMS?$count=true&$select=Name,Team_Id&$orderby=Team_Id desc"
@@ -49382,9 +51429,16 @@ sap.ui.define([
49382
51429
  oBinding = that.oView.byId("table").getBinding("items");
49383
51430
 
49384
51431
  oBinding.attachCreateActivate(function (oEvent) {
49385
- if (!oEvent.getParameter("context").getProperty("Team_Id")) {
51432
+ const oContext = oEvent.getParameter("context");
51433
+ assert.ok(oContext.isInactive());
51434
+ assert.strictEqual(
51435
+ oContext.isInactive(),
51436
+ oContext.getProperty("@$ui5.context.isInactive"));
51437
+ if (!oContext.getProperty("Team_Id")) {
49386
51438
  // code under test
49387
51439
  oEvent.preventDefault();
51440
+ } else {
51441
+ oContext.setProperty("BudgetCurrency", "EUR");
49388
51442
  }
49389
51443
  });
49390
51444
 
@@ -49432,6 +51486,7 @@ sap.ui.define([
49432
51486
  method : "POST",
49433
51487
  url : "TEAMS",
49434
51488
  payload : {
51489
+ BudgetCurrency : "EUR",
49435
51490
  Name : "Team #1 edited",
49436
51491
  Team_Id : "TEAM_01"
49437
51492
  }
@@ -49484,6 +51539,7 @@ sap.ui.define([
49484
51539
  method : "POST",
49485
51540
  url : "TEAMS",
49486
51541
  payload : {
51542
+ BudgetCurrency : "EUR",
49487
51543
  Name : "Team #2 inactive",
49488
51544
  Team_Id : "TEAM_02"
49489
51545
  }
@@ -50961,6 +53017,69 @@ sap.ui.define([
50961
53017
  });
50962
53018
  });
50963
53019
 
53020
+ //*********************************************************************************************
53021
+ // Scenario: A list of teams with an expanded list of employees. Create a team and show it in
53022
+ // the object page. This object page has another employee table w/ own requests. Immediately
53023
+ // (before it starts reading) create an employee in this list.
53024
+ // BCP: 2380101762
53025
+ QUnit.test("BCP: 2380101762", async function (assert) {
53026
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
53027
+ const sView = `
53028
+ <Table id="teams" items="{/TEAMS}">
53029
+ <Text id="teamId" text="{Team_Id}"/>
53030
+ <List items="{path : 'TEAM_2_EMPLOYEES', templateShareable : true}">
53031
+ <CustomListItem>
53032
+ <Text text="{ID}"/>
53033
+ </CustomListItem>
53034
+ </List>
53035
+ </Table>
53036
+ <FlexBox id="objectPage">
53037
+ <Table id="employees" items="{path : 'TEAM_2_EMPLOYEES', parameters : {$$ownRequest : true}}">
53038
+ <Text id="employeeId" text="{ID}"/>
53039
+ </Table>
53040
+ </FlexBox>
53041
+ `;
53042
+ this.expectRequest("TEAMS?$select=Team_Id&$expand=TEAM_2_EMPLOYEES($select=ID)"
53043
+ + "&$skip=0&$top=100",
53044
+ {value : []})
53045
+ .expectChange("teamId", [])
53046
+ .expectChange("employeeId", []);
53047
+
53048
+ await this.createView(assert, sView, oModel);
53049
+
53050
+ this.expectChange("teamId", ["new"])
53051
+ .expectRequest({
53052
+ method : "POST",
53053
+ url : "TEAMS",
53054
+ payload : {Team_Id : "new", TEAM_2_EMPLOYEES : []}
53055
+ }, {Team_Id : "new", TEAM_2_EMPLOYEES : []});
53056
+
53057
+ const oTeamContext = this.oView.byId("teams").getBinding("items").create(
53058
+ {Team_Id : "new", TEAM_2_EMPLOYEES : []});
53059
+
53060
+ await Promise.all([
53061
+ oTeamContext,
53062
+ this.waitForChanges(assert, "create team")
53063
+ ]);
53064
+
53065
+ this.expectChange("employeeId", ["E1"])
53066
+ .expectRequest({
53067
+ method : "POST",
53068
+ url : "TEAMS('new')/TEAM_2_EMPLOYEES",
53069
+ payload : {ID : "E1"}
53070
+ }, {ID : "E1", Team_Id : "new"})
53071
+ // the binding does not get the data from the deep create using another binding
53072
+ .expectRequest("TEAMS('new')/TEAM_2_EMPLOYEES?$select=ID&$skip=0&$top=100",
53073
+ {value : []});
53074
+
53075
+ this.oView.byId("objectPage").setBindingContext(oTeamContext);
53076
+
53077
+ await Promise.all([
53078
+ this.oView.byId("employees").getBinding("items").create({ID : "E1"}, true),
53079
+ this.waitForChanges(assert, "create employee")
53080
+ ]);
53081
+ });
53082
+
50964
53083
  //*********************************************************************************************
50965
53084
  // Scenario:
50966
53085
  // (1) Binding for a part of a structural instance annotation works without binding the
@@ -52320,7 +54439,7 @@ sap.ui.define([
52320
54439
  // modify internal states of the binding. Calling ODLB#getLength afterwards works as expected.
52321
54440
  //
52322
54441
  // Simulate a possible infinite loop here.
52323
- // If a t:Table (with MDCTable wrapper) uses VisibleRowCountMode=Auto, then there is a "change"
54442
+ // If a t:Table (with MDCTable wrapper) uses rowMode=Auto, then there is a "change"
52324
54443
  // listener in RowMode#updateTable. It calls ODLB#getContexts (which calls fetchContexts ->
52325
54444
  // createContexts -> modifies bLengthFinal) and fires a "rowsUpdated" event, where another
52326
54445
  // listener in MDCTable#_handleUpdateFinished reacts on. That listener calls