@openui5/sap.ui.core 1.115.1 → 1.117.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 (685) hide show
  1. package/.dtsgenrc +18 -0
  2. package/.eslintrc.json +1 -11
  3. package/.reuse/dep5 +0 -5
  4. package/THIRDPARTY.txt +1 -7
  5. package/package.json +1 -1
  6. package/src/jquery.sap.global.js +1 -1
  7. package/src/jquery.sap.properties.js +1 -1
  8. package/src/jquery.sap.resources.js +1 -1
  9. package/src/jquery.sap.script.js +1 -1
  10. package/src/jquery.sap.sjax.js +2 -2
  11. package/src/jquery.sap.storage.js +3 -3
  12. package/src/sap/base/Event.js +106 -0
  13. package/src/sap/base/Eventing.js +319 -0
  14. package/src/sap/base/config/MemoryConfigurationProvider.js +10 -1
  15. package/src/sap/base/config.js +3 -2
  16. package/src/sap/base/i18n/Formatting.js +989 -0
  17. package/src/sap/base/i18n/LanguageTag.js +189 -0
  18. package/src/sap/base/i18n/Localization.js +710 -0
  19. package/src/sap/base/i18n/ResourceBundle.js +5 -20
  20. package/src/sap/base/i18n/date/CalendarType.js +54 -0
  21. package/src/sap/base/i18n/date/CalendarWeekNumbering.js +105 -0
  22. package/src/sap/base/i18n/date/TimezoneUtils.js +287 -0
  23. package/src/sap/base/util/JSTokenizer.js +1 -1
  24. package/src/sap/base/util/fetch.js +4 -4
  25. package/src/sap/base/util/mixedFetch.js +2 -2
  26. package/src/sap/base/util/restricted/_CancelablePromise.js +1 -1
  27. package/src/sap/base/util/restricted/_castArray.js +1 -1
  28. package/src/sap/base/util/restricted/_compact.js +1 -1
  29. package/src/sap/base/util/restricted/_curry.js +1 -1
  30. package/src/sap/base/util/restricted/_debounce.js +1 -1
  31. package/src/sap/base/util/restricted/_difference.js +1 -1
  32. package/src/sap/base/util/restricted/_differenceBy.js +1 -1
  33. package/src/sap/base/util/restricted/_differenceWith.js +1 -1
  34. package/src/sap/base/util/restricted/_flatMap.js +1 -1
  35. package/src/sap/base/util/restricted/_flatMapDeep.js +1 -1
  36. package/src/sap/base/util/restricted/_flatMapDepth.js +1 -1
  37. package/src/sap/base/util/restricted/_flatten.js +1 -1
  38. package/src/sap/base/util/restricted/_flattenDeep.js +1 -1
  39. package/src/sap/base/util/restricted/_flattenDepth.js +1 -1
  40. package/src/sap/base/util/restricted/_intersection.js +1 -1
  41. package/src/sap/base/util/restricted/_intersectionBy.js +1 -1
  42. package/src/sap/base/util/restricted/_intersectionWith.js +1 -1
  43. package/src/sap/base/util/restricted/_isEqual.js +1 -1
  44. package/src/sap/base/util/restricted/_isEqualWith.js +1 -1
  45. package/src/sap/base/util/restricted/_isNil.js +1 -1
  46. package/src/sap/base/util/restricted/_max.js +1 -1
  47. package/src/sap/base/util/restricted/_merge.js +1 -1
  48. package/src/sap/base/util/restricted/_mergeWith.js +1 -1
  49. package/src/sap/base/util/restricted/_min.js +1 -1
  50. package/src/sap/base/util/restricted/_omit.js +1 -1
  51. package/src/sap/base/util/restricted/_pick.js +1 -1
  52. package/src/sap/base/util/restricted/_pickBy.js +1 -1
  53. package/src/sap/base/util/restricted/_throttle.js +1 -1
  54. package/src/sap/base/util/restricted/_toArray.js +1 -1
  55. package/src/sap/base/util/restricted/_union.js +1 -1
  56. package/src/sap/base/util/restricted/_unionBy.js +1 -1
  57. package/src/sap/base/util/restricted/_unionWith.js +1 -1
  58. package/src/sap/base/util/restricted/_uniq.js +1 -1
  59. package/src/sap/base/util/restricted/_uniqBy.js +1 -1
  60. package/src/sap/base/util/restricted/_uniqWith.js +1 -1
  61. package/src/sap/base/util/restricted/_without.js +1 -1
  62. package/src/sap/base/util/restricted/_xor.js +1 -1
  63. package/src/sap/base/util/restricted/_xorBy.js +1 -1
  64. package/src/sap/base/util/restricted/_xorWith.js +1 -1
  65. package/src/sap/base/util/restricted/_zipObject.js +1 -1
  66. package/src/sap/base/util/restricted/_zipObjectDeep.js +1 -1
  67. package/src/sap/base/util/syncFetch.js +2 -2
  68. package/src/sap/ui/Device.js +3 -3
  69. package/src/sap/ui/Global.js +4 -4
  70. package/src/sap/ui/base/Event.js +6 -4
  71. package/src/sap/ui/base/EventProvider.js +4 -12
  72. package/src/sap/ui/base/Interface.js +1 -1
  73. package/src/sap/ui/base/ManagedObject.js +9 -15
  74. package/src/sap/ui/base/ManagedObjectMetadata.js +33 -12
  75. package/src/sap/ui/base/Metadata.js +1 -1
  76. package/src/sap/ui/base/Object.js +1 -1
  77. package/src/sap/ui/base/ObjectPool.js +1 -1
  78. package/src/sap/ui/base/SyncPromise.js +10 -5
  79. package/src/sap/ui/core/.library +3 -3
  80. package/src/sap/ui/core/AccessKeysEnablement.js +10 -5
  81. package/src/sap/ui/core/AnimationMode.js +49 -0
  82. package/src/sap/ui/core/BusyIndicator.js +33 -42
  83. package/src/sap/ui/core/CalendarType.js +11 -37
  84. package/src/sap/ui/core/Component.js +4 -5
  85. package/src/sap/ui/core/ComponentContainer.js +1 -1
  86. package/src/sap/ui/core/ComponentMetadata.js +2 -2
  87. package/src/sap/ui/core/ComponentSupport.js +1 -1
  88. package/src/sap/ui/core/ConfigTest.js +17 -0
  89. package/src/sap/ui/core/Configuration.js +409 -1282
  90. package/src/sap/ui/core/Control.js +7 -12
  91. package/src/sap/ui/core/ControlBehavior.js +157 -0
  92. package/src/sap/ui/core/Core.js +126 -132
  93. package/src/sap/ui/core/CustomData.js +1 -1
  94. package/src/sap/ui/core/DeclarativeSupport.js +1 -1
  95. package/src/sap/ui/core/Element.js +14 -3
  96. package/src/sap/ui/core/ElementMetadata.js +2 -4
  97. package/src/sap/ui/core/EnabledPropagator.js +1 -1
  98. package/src/sap/ui/core/EventBus.js +1 -1
  99. package/src/sap/ui/core/Fragment.js +1 -1
  100. package/src/sap/ui/core/HTML.js +1 -1
  101. package/src/sap/ui/core/History.js +1 -1
  102. package/src/sap/ui/core/Icon.js +1 -1
  103. package/src/sap/ui/core/IconPool.js +1 -2
  104. package/src/sap/ui/core/IndicationColorSupport.js +1 -1
  105. package/src/sap/ui/core/IntervalTrigger.js +1 -1
  106. package/src/sap/ui/core/InvisibleMessage.js +5 -7
  107. package/src/sap/ui/core/InvisibleRenderer.js +1 -1
  108. package/src/sap/ui/core/InvisibleText.js +12 -12
  109. package/src/sap/ui/core/Item.js +1 -1
  110. package/src/sap/ui/core/LabelEnablement.js +1 -1
  111. package/src/sap/ui/core/LayoutData.js +1 -1
  112. package/src/sap/ui/core/Lib.js +126 -38
  113. package/src/sap/ui/core/ListItem.js +1 -1
  114. package/src/sap/ui/core/LocalBusyIndicator.js +1 -1
  115. package/src/sap/ui/core/Locale.js +154 -430
  116. package/src/sap/ui/core/LocaleData.js +50 -14
  117. package/src/sap/ui/core/Manifest.js +5 -5
  118. package/src/sap/ui/core/Message.js +1 -1
  119. package/src/sap/ui/core/Popup.js +37 -50
  120. package/src/sap/ui/core/RenderManager.js +1 -1
  121. package/src/sap/ui/core/Renderer.js +1 -1
  122. package/src/sap/ui/core/Rendering.js +1 -1
  123. package/src/sap/ui/core/ResizeHandler.js +1 -1
  124. package/src/sap/ui/core/ScrollBar.js +1 -1
  125. package/src/sap/ui/core/SeparatorItem.js +1 -1
  126. package/src/sap/ui/core/Shortcut.js +11 -9
  127. package/src/sap/ui/core/StaticArea.js +31 -17
  128. package/src/sap/ui/core/Theming.js +458 -0
  129. package/src/sap/ui/core/Title.js +1 -1
  130. package/src/sap/ui/core/TooltipBase.js +1 -1
  131. package/src/sap/ui/core/UIArea.js +1 -1
  132. package/src/sap/ui/core/UIComponent.js +1 -1
  133. package/src/sap/ui/core/UIComponentMetadata.js +1 -1
  134. package/src/sap/ui/core/ValueStateSupport.js +1 -1
  135. package/src/sap/ui/core/VariantLayoutData.js +1 -1
  136. package/src/sap/ui/core/XMLComposite.js +1 -1
  137. package/src/sap/ui/core/XMLCompositeMetadata.js +1 -1
  138. package/src/sap/ui/core/XMLTemplateProcessor.js +28 -5
  139. package/src/sap/ui/core/_IconRegistry.js +89 -12
  140. package/src/sap/ui/core/boot/_bootConfig.js +137 -0
  141. package/src/sap/ui/core/boot/_runBoot.js +16 -0
  142. package/src/sap/ui/core/boot/initDOM.js +96 -0
  143. package/src/sap/ui/core/boot/loadCalendar.js +50 -0
  144. package/src/sap/ui/core/boot/loadManifest.js +55 -0
  145. package/src/sap/ui/core/boot/loadModules.js +80 -0
  146. package/src/sap/ui/core/boot/manifest.json +11 -0
  147. package/src/sap/ui/core/boot/onInit.js +44 -0
  148. package/src/sap/ui/core/boot.js +107 -0
  149. package/src/sap/ui/core/date/CalendarWeekNumbering.js +12 -83
  150. package/src/sap/ui/core/date/UI5Date.js +10 -4
  151. package/src/sap/ui/core/delegate/ItemNavigation.js +8 -10
  152. package/src/sap/ui/core/delegate/ScrollEnablement.js +5 -5
  153. package/src/sap/ui/core/dnd/DragDropBase.js +1 -1
  154. package/src/sap/ui/core/dnd/DragDropInfo.js +1 -1
  155. package/src/sap/ui/core/dnd/DragInfo.js +1 -1
  156. package/src/sap/ui/core/dnd/DropInfo.js +1 -1
  157. package/src/sap/ui/core/format/DateFormat.js +33 -27
  158. package/src/sap/ui/core/format/TimezoneUtil.js +15 -273
  159. package/src/sap/ui/core/hyphenation/Hyphenation.js +1 -1
  160. package/src/sap/ui/core/library.js +32 -6
  161. package/src/sap/ui/core/message/ControlMessageProcessor.js +1 -1
  162. package/src/sap/ui/core/message/Message.js +1 -1
  163. package/src/sap/ui/core/message/MessageManager.js +1 -1
  164. package/src/sap/ui/core/message/MessageMixin.js +6 -5
  165. package/src/sap/ui/core/message/MessageParser.js +1 -1
  166. package/src/sap/ui/core/message/MessageProcessor.js +1 -1
  167. package/src/sap/ui/core/messagebundle_ar.properties +57 -55
  168. package/src/sap/ui/core/messagebundle_bg.properties +57 -55
  169. package/src/sap/ui/core/messagebundle_ca.properties +30 -28
  170. package/src/sap/ui/core/messagebundle_cs.properties +44 -42
  171. package/src/sap/ui/core/messagebundle_cy.properties +59 -57
  172. package/src/sap/ui/core/messagebundle_da.properties +57 -55
  173. package/src/sap/ui/core/messagebundle_de.properties +59 -57
  174. package/src/sap/ui/core/messagebundle_el.properties +48 -46
  175. package/src/sap/ui/core/messagebundle_en.properties +59 -57
  176. package/src/sap/ui/core/messagebundle_en_GB.properties +59 -57
  177. package/src/sap/ui/core/messagebundle_en_US_sappsd.properties +2 -0
  178. package/src/sap/ui/core/messagebundle_en_US_saprigi.properties +2 -0
  179. package/src/sap/ui/core/messagebundle_en_US_saptrc.properties +3 -0
  180. package/src/sap/ui/core/messagebundle_es.properties +48 -46
  181. package/src/sap/ui/core/messagebundle_es_MX.properties +58 -56
  182. package/src/sap/ui/core/messagebundle_et.properties +55 -53
  183. package/src/sap/ui/core/messagebundle_fi.properties +51 -49
  184. package/src/sap/ui/core/messagebundle_fr.properties +36 -34
  185. package/src/sap/ui/core/messagebundle_fr_CA.properties +21 -19
  186. package/src/sap/ui/core/messagebundle_hi.properties +42 -40
  187. package/src/sap/ui/core/messagebundle_hr.properties +57 -55
  188. package/src/sap/ui/core/messagebundle_hu.properties +58 -56
  189. package/src/sap/ui/core/messagebundle_id.properties +59 -57
  190. package/src/sap/ui/core/messagebundle_it.properties +75 -73
  191. package/src/sap/ui/core/messagebundle_iw.properties +59 -57
  192. package/src/sap/ui/core/messagebundle_ja.properties +50 -48
  193. package/src/sap/ui/core/messagebundle_kk.properties +44 -42
  194. package/src/sap/ui/core/messagebundle_ko.properties +20 -18
  195. package/src/sap/ui/core/messagebundle_lt.properties +59 -57
  196. package/src/sap/ui/core/messagebundle_lv.properties +59 -57
  197. package/src/sap/ui/core/messagebundle_ms.properties +60 -58
  198. package/src/sap/ui/core/messagebundle_nl.properties +58 -56
  199. package/src/sap/ui/core/messagebundle_no.properties +56 -54
  200. package/src/sap/ui/core/messagebundle_pl.properties +56 -54
  201. package/src/sap/ui/core/messagebundle_pt.properties +58 -56
  202. package/src/sap/ui/core/messagebundle_pt_PT.properties +58 -56
  203. package/src/sap/ui/core/messagebundle_ro.properties +59 -57
  204. package/src/sap/ui/core/messagebundle_ru.properties +57 -55
  205. package/src/sap/ui/core/messagebundle_sh.properties +59 -57
  206. package/src/sap/ui/core/messagebundle_sk.properties +57 -55
  207. package/src/sap/ui/core/messagebundle_sl.properties +58 -56
  208. package/src/sap/ui/core/messagebundle_sv.properties +54 -52
  209. package/src/sap/ui/core/messagebundle_th.properties +18 -16
  210. package/src/sap/ui/core/messagebundle_tr.properties +58 -56
  211. package/src/sap/ui/core/messagebundle_uk.properties +59 -57
  212. package/src/sap/ui/core/messagebundle_vi.properties +59 -57
  213. package/src/sap/ui/core/messagebundle_zh_CN.properties +58 -56
  214. package/src/sap/ui/core/messagebundle_zh_TW.properties +58 -56
  215. package/src/sap/ui/core/mvc/HTMLView.js +1 -1
  216. package/src/sap/ui/core/mvc/JSONView.js +1 -1
  217. package/src/sap/ui/core/mvc/JSView.js +1 -1
  218. package/src/sap/ui/core/mvc/TemplateView.js +1 -1
  219. package/src/sap/ui/core/mvc/View.js +1 -1
  220. package/src/sap/ui/core/mvc/XMLView.js +14 -2
  221. package/src/sap/ui/core/plugin/DeclarativeSupport.js +1 -1
  222. package/src/sap/ui/core/plugin/LessSupport.js +14 -16
  223. package/src/sap/ui/core/plugin/TemplatingSupport.js +1 -1
  224. package/src/sap/ui/core/postmessage/Bus.js +1 -1
  225. package/src/sap/ui/core/postmessage/confirmationDialog.js +1 -1
  226. package/src/sap/ui/core/routing/HashChanger.js +1 -0
  227. package/src/sap/ui/core/routing/Route.js +1 -0
  228. package/src/sap/ui/core/routing/Router.js +3 -1
  229. package/src/sap/ui/core/rules/Config.support.js +2 -2
  230. package/src/sap/ui/core/rules/Misc.support.js +1 -1
  231. package/src/sap/ui/core/rules/Model.support.js +3 -1
  232. package/src/sap/ui/core/search/OpenSearchProvider.js +1 -1
  233. package/src/sap/ui/core/search/SearchProvider.js +1 -1
  234. package/src/sap/ui/core/service/Service.js +1 -1
  235. package/src/sap/ui/core/service/ServiceFactory.js +1 -1
  236. package/src/sap/ui/core/service/ServiceFactoryRegistry.js +1 -1
  237. package/src/sap/ui/core/support/Plugin.js +1 -1
  238. package/src/sap/ui/core/support/Support.js +7 -4
  239. package/src/sap/ui/core/support/controls/TimelineOverview.js +1 -1
  240. package/src/sap/ui/core/support/plugins/ControlTree.js +2 -2
  241. package/src/sap/ui/core/support/plugins/Interaction.js +1 -1
  242. package/src/sap/ui/core/support/plugins/LocalStorage.js +1 -1
  243. package/src/sap/ui/core/support/plugins/Performance.js +1 -1
  244. package/src/sap/ui/core/support/plugins/Selector.js +1 -1
  245. package/src/sap/ui/core/support/plugins/TechInfo.js +1 -1
  246. package/src/sap/ui/core/support/plugins/Trace.js +1 -1
  247. package/src/sap/ui/core/support/plugins/ViewInfo.js +1 -1
  248. package/src/sap/ui/core/themes/base/Icon.less +2 -2
  249. package/src/sap/ui/core/themes/base/LocalBusyIndicator.less +4 -4
  250. package/src/sap/ui/core/themes/base/base.less +41 -20
  251. package/src/sap/ui/core/themes/base/fonts/SAP-icons.ttf +0 -0
  252. package/src/sap/ui/core/themes/base/fonts/SAP-icons.woff2 +0 -0
  253. package/src/sap/ui/core/theming/Parameters.js +6 -10
  254. package/src/sap/ui/core/theming/ThemeManager.js +312 -450
  255. package/src/sap/ui/core/tmpl/DOMAttribute.js +1 -1
  256. package/src/sap/ui/core/tmpl/DOMElement.js +5 -10
  257. package/src/sap/ui/core/tmpl/HandlebarsTemplate.js +1 -1
  258. package/src/sap/ui/core/tmpl/Template.js +1 -1
  259. package/src/sap/ui/core/tmpl/TemplateControl.js +1 -1
  260. package/src/sap/ui/core/util/AsyncHintsHelper.js +1 -1
  261. package/src/sap/ui/core/util/Export.js +1 -1
  262. package/src/sap/ui/core/util/ExportCell.js +1 -1
  263. package/src/sap/ui/core/util/ExportColumn.js +1 -1
  264. package/src/sap/ui/core/util/ExportRow.js +1 -1
  265. package/src/sap/ui/core/util/ExportType.js +1 -1
  266. package/src/sap/ui/core/util/ExportTypeCSV.js +1 -1
  267. package/src/sap/ui/core/util/File.js +1 -1
  268. package/src/sap/ui/core/util/LibraryInfo.js +1 -1
  269. package/src/sap/ui/core/util/MockServer.js +4 -5
  270. package/src/sap/ui/core/util/PasteHelper.js +1 -1
  271. package/src/sap/ui/core/util/reflection/BaseTreeModifier.js +3 -1
  272. package/src/sap/ui/core/util/serializer/HTMLViewSerializer.js +1 -1
  273. package/src/sap/ui/core/util/serializer/Serializer.js +1 -1
  274. package/src/sap/ui/core/util/serializer/ViewSerializer.js +1 -1
  275. package/src/sap/ui/core/util/serializer/XMLViewSerializer.js +1 -1
  276. package/src/sap/ui/core/util/serializer/delegate/Delegate.js +1 -1
  277. package/src/sap/ui/core/util/serializer/delegate/HTML.js +1 -1
  278. package/src/sap/ui/core/util/serializer/delegate/XML.js +1 -1
  279. package/src/sap/ui/core/ws/ReadyState.js +1 -1
  280. package/src/sap/ui/core/ws/SapPcpWebSocket.js +1 -1
  281. package/src/sap/ui/core/ws/WebSocket.js +1 -1
  282. package/src/sap/ui/debug/ControlTree.js +1 -1
  283. package/src/sap/ui/debug/DebugEnv.js +1 -1
  284. package/src/sap/ui/debug/PropertyList.js +1 -1
  285. package/src/sap/ui/events/PseudoEvents.js +17 -9
  286. package/src/sap/ui/model/Binding.js +19 -15
  287. package/src/sap/ui/model/ClientModel.js +1 -1
  288. package/src/sap/ui/model/CompositeBinding.js +57 -19
  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/DataState.js +1 -1
  292. package/src/sap/ui/model/ListBinding.js +42 -1
  293. package/src/sap/ui/model/MetaModel.js +1 -1
  294. package/src/sap/ui/model/Model.js +5 -4
  295. package/src/sap/ui/model/PropertyBinding.js +10 -0
  296. package/src/sap/ui/model/SelectionModel.js +1 -1
  297. package/src/sap/ui/model/SimpleType.js +4 -1
  298. package/src/sap/ui/model/TreeAutoExpandMode.js +1 -1
  299. package/src/sap/ui/model/Type.js +1 -1
  300. package/src/sap/ui/model/analytics/AnalyticalBinding.js +166 -79
  301. package/src/sap/ui/model/analytics/AnalyticalVersionInfo.js +4 -3
  302. package/src/sap/ui/model/analytics/BatchResponseCollector.js +2 -2
  303. package/src/sap/ui/model/analytics/ODataModelAdapter.js +14 -27
  304. package/src/sap/ui/model/analytics/odata4analytics.js +6 -12
  305. package/src/sap/ui/model/base/ManagedObjectModel.js +3 -2
  306. package/src/sap/ui/model/json/JSONModel.js +6 -1
  307. package/src/sap/ui/model/message/MessageModel.js +1 -1
  308. package/src/sap/ui/model/odata/ODataAnnotations.js +1 -1
  309. package/src/sap/ui/model/odata/ODataMessageParser.js +1 -1
  310. package/src/sap/ui/model/odata/ODataMetaModel.js +191 -5
  311. package/src/sap/ui/model/odata/ODataMetadata.js +38 -4
  312. package/src/sap/ui/model/odata/ODataModel.js +1 -1
  313. package/src/sap/ui/model/odata/type/Boolean.js +1 -1
  314. package/src/sap/ui/model/odata/type/Byte.js +1 -1
  315. package/src/sap/ui/model/odata/type/Currency.js +1 -1
  316. package/src/sap/ui/model/odata/type/Date.js +1 -1
  317. package/src/sap/ui/model/odata/type/DateTime.js +1 -1
  318. package/src/sap/ui/model/odata/type/DateTimeBase.js +8 -1
  319. package/src/sap/ui/model/odata/type/DateTimeOffset.js +1 -1
  320. package/src/sap/ui/model/odata/type/DateTimeWithTimezone.js +1 -1
  321. package/src/sap/ui/model/odata/type/Decimal.js +1 -1
  322. package/src/sap/ui/model/odata/type/Double.js +1 -1
  323. package/src/sap/ui/model/odata/type/Guid.js +1 -1
  324. package/src/sap/ui/model/odata/type/Int.js +1 -1
  325. package/src/sap/ui/model/odata/type/Int16.js +1 -1
  326. package/src/sap/ui/model/odata/type/Int32.js +1 -1
  327. package/src/sap/ui/model/odata/type/Int64.js +1 -1
  328. package/src/sap/ui/model/odata/type/ODataType.js +3 -3
  329. package/src/sap/ui/model/odata/type/Raw.js +1 -1
  330. package/src/sap/ui/model/odata/type/SByte.js +1 -1
  331. package/src/sap/ui/model/odata/type/Single.js +1 -1
  332. package/src/sap/ui/model/odata/type/Stream.js +1 -1
  333. package/src/sap/ui/model/odata/type/String.js +1 -1
  334. package/src/sap/ui/model/odata/type/Time.js +1 -1
  335. package/src/sap/ui/model/odata/type/TimeOfDay.js +1 -1
  336. package/src/sap/ui/model/odata/type/Unit.js +1 -1
  337. package/src/sap/ui/model/odata/v2/Context.js +3 -2
  338. package/src/sap/ui/model/odata/v2/ODataAnnotations.js +1 -1
  339. package/src/sap/ui/model/odata/v2/ODataListBinding.js +14 -3
  340. package/src/sap/ui/model/odata/v2/ODataModel.js +46 -32
  341. package/src/sap/ui/model/odata/v2/ODataTreeBinding.js +1 -1
  342. package/src/sap/ui/model/odata/v4/AnnotationHelper.js +4 -4
  343. package/src/sap/ui/model/odata/v4/Context.js +39 -32
  344. package/src/sap/ui/model/odata/v4/ODataBinding.js +85 -52
  345. package/src/sap/ui/model/odata/v4/ODataContextBinding.js +23 -19
  346. package/src/sap/ui/model/odata/v4/ODataListBinding.js +139 -50
  347. package/src/sap/ui/model/odata/v4/ODataMetaModel.js +30 -36
  348. package/src/sap/ui/model/odata/v4/ODataModel.js +49 -44
  349. package/src/sap/ui/model/odata/v4/ODataParentBinding.js +72 -37
  350. package/src/sap/ui/model/odata/v4/ODataPropertyBinding.js +34 -29
  351. package/src/sap/ui/model/odata/v4/lib/_AggregationCache.js +95 -9
  352. package/src/sap/ui/model/odata/v4/lib/_AggregationHelper.js +25 -27
  353. package/src/sap/ui/model/odata/v4/lib/_Cache.js +95 -209
  354. package/src/sap/ui/model/odata/v4/lib/_Helper.js +168 -1
  355. package/src/sap/ui/model/odata/v4/lib/_MetadataRequestor.js +14 -5
  356. package/src/sap/ui/model/odata/v4/lib/_Requestor.js +34 -19
  357. package/src/sap/ui/model/odata/v4/lib/_V2MetadataConverter.js +4 -4
  358. package/src/sap/ui/model/odata/v4/lib/_V2Requestor.js +1 -1
  359. package/src/sap/ui/model/resource/ResourceModel.js +1 -1
  360. package/src/sap/ui/model/type/Boolean.js +1 -1
  361. package/src/sap/ui/model/type/Currency.js +1 -1
  362. package/src/sap/ui/model/type/Date.js +1 -1
  363. package/src/sap/ui/model/type/DateInterval.js +1 -1
  364. package/src/sap/ui/model/type/DateTime.js +1 -1
  365. package/src/sap/ui/model/type/DateTimeInterval.js +1 -1
  366. package/src/sap/ui/model/type/FileSize.js +1 -1
  367. package/src/sap/ui/model/type/Float.js +1 -1
  368. package/src/sap/ui/model/type/Integer.js +1 -1
  369. package/src/sap/ui/model/type/String.js +1 -1
  370. package/src/sap/ui/model/type/Time.js +1 -1
  371. package/src/sap/ui/model/type/TimeInterval.js +1 -1
  372. package/src/sap/ui/model/type/Unit.js +1 -1
  373. package/src/sap/ui/model/xml/XMLModel.js +1 -1
  374. package/src/sap/ui/qunit/utils/ControlIterator.js +1 -1
  375. package/src/sap/ui/qunit/utils/MemoryLeakCheck.js +1 -1
  376. package/src/sap/ui/test/Opa5.js +1 -1
  377. package/src/sap/ui/test/TestUtils.js +1 -1
  378. package/src/sap/ui/test/autowaiter/_autoWaiter.js +1 -1
  379. package/src/sap/ui/test/generic/TestBase.js +1 -1
  380. package/src/sap/ui/test/generic/_EnforceSemanticRendering.js +1 -3
  381. package/src/sap/ui/test/gherkin/simpleGherkinParser.js +10 -5
  382. package/src/sap/ui/test/matchers/LabelFor.js +1 -0
  383. package/src/sap/ui/test/matchers/_Visitor.js +6 -1
  384. package/src/sap/ui/test/starter/_setupAndStart.js +2 -5
  385. package/src/sap/ui/thirdparty/caja-html-sanitizer.js +111 -96
  386. package/src/sap/ui/thirdparty/qunit-2.js +9 -3
  387. package/src/sap/ui/util/ActivityDetection.js +7 -1
  388. package/src/sap/ui/util/Mobile.js +21 -14
  389. package/src/sap/ui/util/Storage.js +1 -1
  390. package/src/sap-ui-boot.js +23 -6
  391. package/src/ui5-boot.js +50 -0
  392. package/src/ui5loader-autoconfig.js +150 -75
  393. package/src/ui5loader.js +458 -514
  394. package/test/sap/ui/core/Device.js +1 -1
  395. package/test/sap/ui/core/FormatHelper.js +3 -2
  396. package/test/sap/ui/core/demokit/docuindex.json +6 -0
  397. package/test/sap/ui/core/demokit/sample/OpaAction/applicationUnderTest/view/Main.view.xml +1 -0
  398. package/test/sap/ui/core/demokit/sample/OpaBusyIndicator/OpaBusyIndicator.js +1 -1
  399. package/test/sap/ui/core/demokit/sample/OpaMatchers/OpaMatchers.js +2 -2
  400. package/test/sap/ui/core/demokit/sample/ViewTemplate/types/MIT.ODataTypes.html +9 -14
  401. package/test/sap/ui/core/demokit/sample/ViewTemplate/types/Opa.qunit.js +7 -0
  402. package/test/sap/ui/core/demokit/sample/ViewTemplate/types/Template.controller.js +2 -2
  403. package/test/sap/ui/core/demokit/sample/common/pages/Any.js +1 -1
  404. package/test/sap/ui/core/demokit/sample/odata/v2/AutoExpand/AutoExpand.view.xml +24 -5
  405. package/test/sap/ui/core/demokit/sample/odata/v4/Ancestry/Main.view.xml +24 -6
  406. package/test/sap/ui/core/demokit/sample/odata/v4/DataAggregation/DataAggregation.view.xml +20 -5
  407. package/test/sap/ui/core/demokit/sample/odata/v4/DataAggregation/Opa.qunit.js +2 -1
  408. package/test/sap/ui/core/demokit/sample/odata/v4/DataAggregation/tests/filter.js +2 -2
  409. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/Component.js +27 -0
  410. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/ListReport.controller.js +43 -0
  411. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/ListReport.view.xml +47 -0
  412. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/Main.controller.js +27 -0
  413. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/Main.view.xml +7 -0
  414. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/NotFound.view.xml +8 -0
  415. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/ObjectPage.controller.js +123 -0
  416. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/ObjectPage.view.xml +92 -0
  417. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/Opa.qunit.html +27 -0
  418. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/Opa.qunit.js +70 -0
  419. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/README.html +55 -0
  420. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/SandboxModel.js +56 -0
  421. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/data/POST-SalesOrderList.json +66 -0
  422. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/data/SalesOrderList('0500000000')-SO_2_SOITEM.json +57 -0
  423. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/data/SalesOrderList('0500000000').json +20 -0
  424. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/data/SalesOrderList('0500000001').json +9 -0
  425. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/data/SalesOrderList('0500000007')-SO_2_BP.json +12 -0
  426. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/data/SalesOrderList.json +62 -0
  427. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/data/VH_CurrencyCode.json +85 -0
  428. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/data/VH_CurrencyCode.xml +185 -0
  429. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/data/VH_ProductID.json +93 -0
  430. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/data/VH_ProductID.xml +262 -0
  431. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/data/metadata.xml +1779 -0
  432. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/manifest.json +134 -0
  433. package/test/sap/ui/core/demokit/sample/odata/v4/DeepCreate/pages/Main.js +119 -0
  434. package/test/sap/ui/core/demokit/sample/odata/v4/Draft/Opa.qunit.js +2 -1
  435. package/test/sap/ui/core/demokit/sample/odata/v4/FieldGroups/Opa.qunit.js +2 -1
  436. package/test/sap/ui/core/demokit/sample/odata/v4/FlatDataAggregation/FlatDataAggregation.view.xml +4 -1
  437. package/test/sap/ui/core/demokit/sample/odata/v4/FlexibleColumnLayout/Opa.qunit.js +2 -1
  438. package/test/sap/ui/core/demokit/sample/odata/v4/GridTable/GridTable.view.xml +12 -3
  439. package/test/sap/ui/core/demokit/sample/odata/v4/LateProperties/Main.controller.js +2 -1
  440. package/test/sap/ui/core/demokit/sample/odata/v4/LateProperties/Opa.OptimisticBatch.qunit.js +2 -1
  441. package/test/sap/ui/core/demokit/sample/odata/v4/LateProperties/Opa.qunit.js +2 -1
  442. package/test/sap/ui/core/demokit/sample/odata/v4/ListBinding/Opa.qunit.js +2 -1
  443. package/test/sap/ui/core/demokit/sample/odata/v4/ListBindingTemplate/Opa.qunit.js +2 -1
  444. package/test/sap/ui/core/demokit/sample/odata/v4/MultipleInlineCreationRowsGrid/Opa.qunit.js +2 -1
  445. package/test/sap/ui/core/demokit/sample/odata/v4/MultipleInlineCreationRowsGrid/pages/Main.js +0 -41
  446. package/test/sap/ui/core/demokit/sample/odata/v4/Products/Opa.qunit.js +2 -1
  447. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/RecursiveHierarchy.view.xml +26 -8
  448. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/data/metadata.xml +4 -0
  449. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrderTP100_V2/Opa.qunit.js +2 -1
  450. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrderTP100_V2/manifest.json +1 -1
  451. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrderTP100_V4/Opa.qunit.js +2 -1
  452. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrderTP100_V4/manifest.json +1 -1
  453. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/Main.controller.js +5 -17
  454. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/Opa.qunit.js +2 -1
  455. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/pages/Main.js +18 -0
  456. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/tests/Create.js +10 -6
  457. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrdersRTATest/Opa.qunit.js +2 -1
  458. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrdersRTATest/manifest.json +18 -0
  459. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrdersTemplate/Opa.qunit.js +2 -1
  460. package/test/sap/ui/core/demokit/sample/odata/v4/ServerDrivenPaging/Main.view.xml +3 -3
  461. package/test/sap/ui/core/demokit/sample/odata/v4/ServerDrivenPaging/Opa.qunit.js +2 -1
  462. package/test/sap/ui/core/demokit/sample/odata/v4/ServerDrivenPaging/pages/Main.js +4 -1
  463. package/test/sap/ui/core/demokit/sample/odata/v4/Sticky/Opa.qunit.js +2 -1
  464. package/test/sap/ui/core/demokit/tutorial/odatav4/06/webapp/controller/App.controller.js +1 -6
  465. package/test/sap/ui/core/demokit/tutorial/odatav4/06/webapp/localService/mockserver.js +1 -0
  466. package/test/sap/ui/core/demokit/tutorial/odatav4/07/webapp/controller/App.controller.js +1 -6
  467. package/test/sap/ui/core/demokit/tutorial/odatav4/07/webapp/localService/mockserver.js +1 -0
  468. package/test/sap/ui/core/demokit/tutorial/odatav4/08/webapp/controller/App.controller.js +1 -6
  469. package/test/sap/ui/core/demokit/tutorial/odatav4/08/webapp/localService/mockserver.js +1 -0
  470. package/test/sap/ui/core/demokit/tutorial/odatav4/08/webapp/test/integration/arrangements/Startup.js +1 -1
  471. package/test/sap/ui/core/demokit/tutorial/odatav4/09/webapp/controller/App.controller.js +1 -6
  472. package/test/sap/ui/core/demokit/tutorial/odatav4/09/webapp/localService/mockserver.js +1 -0
  473. package/test/sap/ui/core/demokit/tutorial/odatav4/10/webapp/controller/App.controller.js +3 -8
  474. package/test/sap/ui/core/demokit/tutorial/odatav4/10/webapp/localService/mockserver.js +1 -0
  475. package/test/sap/ui/core/demokit/tutorial/odatav4/11/webapp/controller/App.controller.js +3 -8
  476. package/test/sap/ui/core/demokit/tutorial/odatav4/11/webapp/localService/mockserver.js +1 -0
  477. package/test/sap/ui/core/demokit/tutorial/odatav4/11/webapp/test/integration/arrangements/Startup.js +1 -1
  478. package/test/sap/ui/core/qunit/CompositeBinding.qunit.js +25 -7
  479. package/test/sap/ui/core/qunit/ControlRenderer.qunit.js +86 -2
  480. package/test/sap/ui/core/qunit/DataState.qunit.js +2 -7
  481. package/test/sap/ui/core/qunit/HTML.qunit.js +31 -31
  482. package/test/sap/ui/core/qunit/IconPool.qunit.js +53 -4
  483. package/test/sap/ui/core/qunit/Lib.qunit.js +55 -2
  484. package/test/sap/ui/core/qunit/LocalBusyIndicator.qunit.js +22 -15
  485. package/test/sap/ui/core/qunit/ManagedObject.qunit.js +5 -3
  486. package/test/sap/ui/core/qunit/ManagedObjectModel.qunit.js +43 -5
  487. package/test/sap/ui/core/qunit/Object.qunit.js +4 -1
  488. package/test/sap/ui/core/qunit/ThemeManager.qunit.js +2 -2
  489. package/test/sap/ui/core/qunit/ThemeParameters.qunit.js +9 -3
  490. package/test/sap/ui/core/qunit/Theming.beforeBootstrap.qunit.js +13 -0
  491. package/test/sap/ui/core/qunit/Theming.qunit.js +247 -0
  492. package/test/sap/ui/core/qunit/analytics/AnalyticalBinding.qunit.js +510 -185
  493. package/test/sap/ui/core/qunit/analytics/AnalyticalTreeBindingAdapter.qunit.js +2 -7
  494. package/test/sap/ui/core/qunit/analytics/ODataModelAdapter.qunit.js +81 -16
  495. package/test/sap/ui/core/qunit/analytics/odata4analytics.qunit.js +20 -29
  496. package/test/sap/ui/core/qunit/app/MessageListBinding.qunit.js +2 -7
  497. package/test/sap/ui/core/qunit/base/Config_cascade.qunit.js +18 -1
  498. package/test/sap/ui/core/qunit/base/i18n/Formatting.qunit.html +24 -0
  499. package/test/sap/ui/core/qunit/base/i18n/Formatting.qunit.js +277 -0
  500. package/test/sap/ui/core/qunit/base/i18n/Localization.qunit.js +282 -0
  501. package/test/sap/ui/core/qunit/base/i18n/ResourceBundle.qunit.js +5 -6
  502. package/test/sap/ui/core/qunit/base/security/sanitizeHTML.qunit.js +17 -0
  503. package/test/sap/ui/core/qunit/bootstrap/BootstrapPreload.qunit.js +1 -2
  504. package/test/sap/ui/core/qunit/bootstrap/BootstrapWithCustomBootTask.beforeBootstrap.qunit.js +13 -12
  505. package/test/sap/ui/core/qunit/bootstrap/Configuration.main.qunit.js +11 -0
  506. package/test/sap/ui/core/qunit/bootstrap/Configuration.qunit.html +4 -3
  507. package/test/sap/ui/core/qunit/bootstrap/Configuration.qunit.js +451 -281
  508. package/test/sap/ui/core/qunit/bootstrap/ThemeVersion.qunit.js +19 -30
  509. package/test/sap/ui/core/qunit/component/Models.qunit.js +12 -30
  510. package/test/sap/ui/core/qunit/component/Models_unavoidablySync.qunit.js +8 -26
  511. package/test/sap/ui/core/qunit/component/testdata/async/lib2/library-preload.js +2 -2
  512. package/test/sap/ui/core/qunit/component/testdata/async/lib2/library-preload.json +1 -1
  513. package/test/sap/ui/core/qunit/component/testdata/async/lib2/library.js +2 -2
  514. package/test/sap/ui/core/qunit/component/testdata/async/lib3/library-preload.js +2 -2
  515. package/test/sap/ui/core/qunit/component/testdata/async/lib3/library-preload.json +1 -1
  516. package/test/sap/ui/core/qunit/component/testdata/async/lib3/library.js +2 -2
  517. package/test/sap/ui/core/qunit/component/testdata/async/lib4/library-preload.js +2 -2
  518. package/test/sap/ui/core/qunit/component/testdata/async/lib4/library-preload.json +1 -1
  519. package/test/sap/ui/core/qunit/component/testdata/async/lib4/library.js +2 -2
  520. package/test/sap/ui/core/qunit/component/testdata/async/manifestcomp/Component-preload.js +1 -1
  521. package/test/sap/ui/core/qunit/component/testdata/async/manifestcomp/Component.js +2 -2
  522. package/test/sap/ui/core/qunit/component/testdata/async/mycomp/Component-preload.js +1 -1
  523. package/test/sap/ui/core/qunit/component/testdata/async/mycomp/Component.js +2 -2
  524. package/test/sap/ui/core/qunit/component/testdata/async/mysubcomp/Component-preload.js +1 -1
  525. package/test/sap/ui/core/qunit/component/testdata/async/mysubcomp/Component.js +2 -3
  526. package/test/sap/ui/core/qunit/component/testdata/customizing/customer/ext/Component.js +0 -4
  527. package/test/sap/ui/core/qunit/component/testdata/customizing/customer/ext/sync/Component.js +2 -6
  528. package/test/sap/ui/core/qunit/component/testdata/customizing/customersub/Component.js +0 -4
  529. package/test/sap/ui/core/qunit/component/testdata/inherit/Component.js +2 -7
  530. package/test/sap/ui/core/qunit/component/testdata/inherit/parent/Component.js +2 -7
  531. package/test/sap/ui/core/qunit/component/testdata/inheritAsync/Component.js +2 -2
  532. package/test/sap/ui/core/qunit/component/testdata/inheritAsync/parentA/Component.js +2 -2
  533. package/test/sap/ui/core/qunit/component/testdata/inheritAsync/parentB/Component.js +2 -2
  534. package/test/sap/ui/core/qunit/component/testdata/inheritAsyncError/Component.js +2 -2
  535. package/test/sap/ui/core/qunit/component/testdata/inheritAsyncError/parentA/Component.js +2 -2
  536. package/test/sap/ui/core/qunit/component/testdata/inheritAsyncError/parentB/Component.js +2 -2
  537. package/test/sap/ui/core/qunit/component/testdata/other/Component.js +2 -7
  538. package/test/sap/ui/core/qunit/component/testdata/terminologies/Component.js +2 -2
  539. package/test/sap/ui/core/qunit/component/testdata/terminologies/component1/Component.js +2 -2
  540. package/test/sap/ui/core/qunit/component/testdata/terminologies/component2/Component.js +2 -2
  541. package/test/sap/ui/core/qunit/component/testdata/terminologies/component3/Component.js +2 -2
  542. package/test/sap/ui/core/qunit/component/testdata/terminologies/component5/Component.js +2 -2
  543. package/test/sap/ui/core/qunit/component/testdata/terminologies/reuse/Component.js +2 -3
  544. package/test/sap/ui/core/qunit/component/testdata/v1/Component.js +2 -7
  545. package/test/sap/ui/core/qunit/component/testdata/v1empty/Component.js +2 -7
  546. package/test/sap/ui/core/qunit/component/testdata/v1inline/Component.js +2 -5
  547. package/test/sap/ui/core/qunit/component/testdata/v1missing/Component.js +2 -7
  548. package/test/sap/ui/core/qunit/component/testdata/v2/Component.js +2 -5
  549. package/test/sap/ui/core/qunit/component/testdata/v2asyncRootView/Component.js +2 -5
  550. package/test/sap/ui/core/qunit/component/testdata/v2empty/Component.js +2 -9
  551. package/test/sap/ui/core/qunit/component/testdata/v2inline/Component.js +2 -5
  552. package/test/sap/ui/core/qunit/component/testdata/v2missing/Component.js +2 -9
  553. package/test/sap/ui/core/qunit/component/testdata/v2version/Component.js +2 -2
  554. package/test/sap/ui/core/qunit/dnd/DragDropInfo.qunit.js +1 -2
  555. package/test/sap/ui/core/qunit/generic/EnforceSemanticRendering.qunit.js +2 -2
  556. package/test/sap/ui/core/qunit/generic/SettersContextReturn.qunit.js +2 -2
  557. package/test/sap/ui/core/qunit/generic/legacy/ControlMemoryLeaks.qunit.js +2 -0
  558. package/test/sap/ui/core/qunit/generic/legacy/DuplicateIdCheck.qunit.js +2 -0
  559. package/test/sap/ui/core/qunit/generic/legacy/SettersContextReturn.qunit.js +2 -2
  560. package/test/sap/ui/core/qunit/gherkin/dataTableUtils.qunit.js +2 -2
  561. package/test/sap/ui/core/qunit/i18n/Locale.qunit.js +0 -52
  562. package/test/sap/ui/core/qunit/i18n/LocaleData.qunit.js +49 -14
  563. package/test/sap/ui/core/qunit/i18n/UI5Date.qunit.js +16 -4
  564. package/test/sap/ui/core/qunit/i18n/UniversalDate.qunit.js +74 -114
  565. package/test/sap/ui/core/qunit/i18n/UniversalDateUtils.qunit.js +34 -39
  566. package/test/sap/ui/core/qunit/i18n/testsuite.i18n.qunit.js +18 -0
  567. package/test/sap/ui/core/qunit/internal/1RingModels.qunit.js +1 -0
  568. package/test/sap/ui/core/qunit/internal/BeforePush.ODataV4.js +28 -0
  569. package/test/sap/ui/core/qunit/internal/BeforePush.html +1 -0
  570. package/test/sap/ui/core/qunit/internal/BeforePush.js +15 -0
  571. package/test/sap/ui/core/qunit/internal/performance/ExpressionParser.performance.qunit.js +1 -0
  572. package/test/sap/ui/core/qunit/json/JSONListBinding.qunit.js +2 -7
  573. package/test/sap/ui/core/qunit/json/JSONPropertyBinding.qunit.js +7 -12
  574. package/test/sap/ui/core/qunit/json/JSONTwoWay.qunit.js +3 -8
  575. package/test/sap/ui/core/qunit/loader/asyncMode.qunit.js +2 -2
  576. package/test/sap/ui/core/qunit/loader/asyncMode_unavoidablySync.qunit.js +1 -1
  577. package/test/sap/ui/core/qunit/loader/fixture/amd-with-export-true/module1.js +2 -2
  578. package/test/sap/ui/core/qunit/loader/testsuite.loader.qunit.js +0 -3
  579. package/test/sap/ui/core/qunit/messages/MessageMixin.qunit.js +2 -7
  580. package/test/sap/ui/core/qunit/messages/messagesUsage.qunit.js +1 -1
  581. package/test/sap/ui/core/qunit/model/Binding.qunit.js +36 -11
  582. package/test/sap/ui/core/qunit/model/ClientListBinding.qunit.js +2 -7
  583. package/test/sap/ui/core/qunit/model/ClientTreeBinding.qunit.js +2 -7
  584. package/test/sap/ui/core/qunit/model/CompositeDataState.qunit.js +2 -7
  585. package/test/sap/ui/core/qunit/model/Context.qunit.js +2 -7
  586. package/test/sap/ui/core/qunit/model/ContextBinding.qunit.js +2 -7
  587. package/test/sap/ui/core/qunit/model/FAR_CUSTOMER_LINE_ITEMS.metadata.xml +2 -0
  588. package/test/sap/ui/core/qunit/model/ListBinding.qunit.js +63 -6
  589. package/test/sap/ui/core/qunit/model/Model.qunit.js +2 -7
  590. package/test/sap/ui/core/qunit/model/PropertyBinding.qunit.js +40 -0
  591. package/test/sap/ui/core/qunit/model/TreeBinding.qunit.js +2 -7
  592. package/test/sap/ui/core/qunit/model/TreeBindingAdapter.qunit.js +2 -7
  593. package/test/sap/ui/core/qunit/mvc/XMLTemplateProcessorRequireXML.qunit.js +51 -0
  594. package/test/sap/ui/core/qunit/mvc/XMLView.qunit.js +9 -8
  595. package/test/sap/ui/core/qunit/mvc/extensions/Controllerextensions.qunit.js +4 -4
  596. package/test/sap/ui/core/qunit/mvc/extensions/Controllerextensions_legacy.qunit.js +4 -4
  597. package/test/sap/ui/core/qunit/mvc/testdata/Async.view.xml +1 -1
  598. package/test/sap/ui/core/qunit/mvc/testdata/AsyncTypedView.js +5 -1
  599. package/test/sap/ui/core/qunit/odata/AnnotationParserNoFakeService.qunit.js +2 -7
  600. package/test/sap/ui/core/qunit/odata/ODataMessageParser.qunit.js +1 -1
  601. package/test/sap/ui/core/qunit/odata/ODataMessageParserNoFakeService.qunit.js +2 -8
  602. package/test/sap/ui/core/qunit/odata/ODataMetadataNoFakeService.qunit.js +68 -9
  603. package/test/sap/ui/core/qunit/odata/type/DateTimeBase.qunit.js +24 -0
  604. package/test/sap/ui/core/qunit/odata/v2/Context.qunit.js +2 -7
  605. package/test/sap/ui/core/qunit/odata/v2/ODataContextBindingNoFakeService.qunit.js +2 -7
  606. package/test/sap/ui/core/qunit/odata/v2/ODataListBindingNoFakeService.qunit.js +31 -17
  607. package/test/sap/ui/core/qunit/odata/v2/ODataModel.integration.qunit.js +260 -56
  608. package/test/sap/ui/core/qunit/odata/v2/ODataModelNoFakeService.qunit.js +70 -15
  609. package/test/sap/ui/core/qunit/odata/v2/ODataPropertyBindingNoFakeService.qunit.js +2 -7
  610. package/test/sap/ui/core/qunit/odata/v2/ODataTreeBindingFlatNoFakeService.qunit.js +4 -9
  611. package/test/sap/ui/core/qunit/odata/v2/ODataTreeBindingNoFakeService.qunit.js +2 -7
  612. package/test/sap/ui/core/qunit/odata/v2/V2ODataModel.qunit.js +1 -1
  613. package/test/sap/ui/core/qunit/odata/v2/_CreatedContextsCache.qunit.js +2 -7
  614. package/test/sap/ui/core/qunit/odata/v4/AnnotationHelper.qunit.js +1 -1
  615. package/test/sap/ui/core/qunit/odata/v4/Context.qunit.js +55 -22
  616. package/test/sap/ui/core/qunit/odata/v4/ODataBinding.qunit.js +184 -151
  617. package/test/sap/ui/core/qunit/odata/v4/ODataContextBinding.qunit.js +60 -30
  618. package/test/sap/ui/core/qunit/odata/v4/ODataListBinding.qunit.js +305 -69
  619. package/test/sap/ui/core/qunit/odata/v4/ODataMetaModel.qunit.js +20 -69
  620. package/test/sap/ui/core/qunit/odata/v4/ODataModel.integration.qunit.js +1282 -255
  621. package/test/sap/ui/core/qunit/odata/v4/ODataModel.qunit.js +90 -61
  622. package/test/sap/ui/core/qunit/odata/v4/ODataModel.realOData.qunit.js +0 -3
  623. package/test/sap/ui/core/qunit/odata/v4/ODataParentBinding.qunit.js +283 -170
  624. package/test/sap/ui/core/qunit/odata/v4/ODataPropertyBinding.qunit.js +103 -78
  625. package/test/sap/ui/core/qunit/odata/v4/data/metadata.json +2 -1
  626. package/test/sap/ui/core/qunit/odata/v4/data/metadata.xml +4 -0
  627. package/test/sap/ui/core/qunit/odata/v4/data/metadata_special_cases.xml +2 -0
  628. package/test/sap/ui/core/qunit/odata/v4/lib/_AggregationCache.qunit.js +151 -1
  629. package/test/sap/ui/core/qunit/odata/v4/lib/_AggregationHelper.qunit.js +24 -11
  630. package/test/sap/ui/core/qunit/odata/v4/lib/_Cache.qunit.js +279 -458
  631. package/test/sap/ui/core/qunit/odata/v4/lib/_Helper.qunit.js +204 -3
  632. package/test/sap/ui/core/qunit/odata/v4/lib/_MetadataRequestor.qunit.js +7 -3
  633. package/test/sap/ui/core/qunit/odata/v4/lib/_Requestor.qunit.js +145 -26
  634. package/test/sap/ui/core/qunit/odata/v4/testsuite.odatav4.qunit.js +4 -0
  635. package/test/sap/ui/core/qunit/opa/_LogCollector.qunit.js +1 -1
  636. package/test/sap/ui/core/qunit/opa/matchers/LabelFor.qunit.js +4 -2
  637. package/test/sap/ui/core/qunit/opa/matchers/_Busy.qunit.js +129 -2
  638. package/test/sap/ui/core/qunit/opa/matchers/_Editable.qunit.js +5 -1
  639. package/test/sap/ui/core/qunit/performance/trace/FESR.qunit.js +5 -0
  640. package/test/sap/ui/core/qunit/resource/ResourceModel.qunit.js +17 -37
  641. package/test/sap/ui/core/qunit/routing/HashChanger.qunit.js +1 -6
  642. package/test/sap/ui/core/qunit/routing/RouterHashChanger.qunit.js +1 -10
  643. package/test/sap/ui/core/qunit/routing/async/Router.qunit.js +1 -22
  644. package/test/sap/ui/core/qunit/routing/async/Target.qunit.js +1 -4
  645. package/test/sap/ui/core/qunit/routing/fixture/Async1.view.xml +1 -1
  646. package/test/sap/ui/core/qunit/rule/model/modelSupport.qunit.js +34 -1
  647. package/test/sap/ui/core/qunit/testdata/fastnavigation/view/FastNavigation.view.xml +2 -2
  648. package/test/sap/ui/core/qunit/testdata/libraries/resourcebundle/lib1/i18n.properties +1 -0
  649. package/test/sap/ui/core/qunit/testdata/libraries/resourcebundle/lib1/library.js +10 -0
  650. package/test/sap/ui/core/qunit/testdata/libraries/resourcebundle/lib1/manifest.json +10 -0
  651. package/test/sap/ui/core/qunit/testdata/libraries/resourcebundle/lib2/library.js +10 -0
  652. package/test/sap/ui/core/qunit/testdata/libraries/resourcebundle/lib2/messagebundle.properties +1 -0
  653. package/test/sap/ui/core/qunit/testdata/xml-require/helper/Formatter.js +7 -4
  654. package/test/sap/ui/core/qunit/testdata/xml-require/view/XMLTemplateProcessorAsync_require_in_html.view.xml +36 -0
  655. package/test/sap/ui/core/qunit/testsuites/testsuite.databinding.qunit.js +3 -0
  656. package/test/sap/ui/core/qunit/testsuites/testsuite.theming.qunit.js +29 -0
  657. package/test/sap/ui/core/qunit/types/DateFormatTimezones.qunit.js +1381 -1570
  658. package/test/sap/ui/core/qunit/types/SimpleType.qunit.js +16 -2
  659. package/test/sap/ui/core/qunit/types/Types.qunit.js +2 -37
  660. package/test/sap/ui/core/qunit/types/testsuite.types.qunit.js +1 -1
  661. package/test/sap/ui/core/qunit/util/Popup.qunit.js +7 -11
  662. package/test/sap/ui/core/qunit/util/SyncPromise.qunit.js +4 -1
  663. package/test/sap/ui/core/qunit/util/XMLPreprocessor.qunit.js +3 -1
  664. package/test/sap/ui/core/qunit/util/jQuery.sap.Version.qunit.js +3 -0
  665. package/test/sap/ui/core/qunit/util/jQuery.sap.measure.qunit.js +16 -11
  666. package/test/sap/ui/core/qunit/util/reflection/BaseTreeModifier.qunit.js +1 -1
  667. package/test/sap/ui/core/qunit/xml/XMLListBinding.qunit.js +1 -3
  668. package/test/sap/ui/core/qunit/xml/XMLModel.qunit.js +4 -14
  669. package/test/sap/ui/core/qunit/xml/XMLPropertyBinding.qunit.js +7 -11
  670. package/test/sap/ui/core/qunit/xml/XMLTreeBinding.qunit.js +1 -1
  671. package/test/sap/ui/core/qunit/xml/XMLTwoWay.qunit.js +3 -7
  672. package/test/sap/ui/core/relnotes/changes-1.115.json +1 -37
  673. package/test/sap/ui/core/relnotes/changes-1.116.json +71 -0
  674. package/test/sap/ui/core/relnotes/changes-1.117.json +127 -0
  675. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/firstItem-contextMenu.ref.lnk +1 -1
  676. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/initial.ref.lnk +1 -1
  677. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/lastItem-contextMenu.ref.lnk +1 -1
  678. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/leftDownBtn-contextMenu.ref.lnk +1 -1
  679. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/myButtonSample-contextMenu.ref.lnk +1 -1
  680. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/rightDownBtn-contextMenu.ref.lnk +1 -1
  681. package/test/sap/ui/core/visual/images/HyphenationPlayground/windows/1600x1200/chrome/horizon/ltr/cozy/19_thirdParty_language_sl.ref.lnk +1 -1
  682. package/test/testsuite/js/samples.js +2 -0
  683. package/ui5.yaml +166 -1
  684. package/src/sap/ui/core/util/MockServerAnnotationsHandler.js +0 -45
  685. /package/test/sap/ui/core/qunit/bootstrap/{GlobalConfigurationSettings.js → Configuration.beforeBootstrap.qunit.js} +0 -0
@@ -24,6 +24,7 @@ sap.ui.define([
24
24
  "sap/ui/model/odata/OperationMode",
25
25
  "sap/ui/model/odata/v4/AnnotationHelper",
26
26
  "sap/ui/model/odata/v4/ODataListBinding",
27
+ "sap/ui/model/odata/v4/ODataMetaModel",
27
28
  "sap/ui/model/odata/v4/ODataModel",
28
29
  "sap/ui/model/odata/v4/ODataPropertyBinding",
29
30
  "sap/ui/model/odata/v4/ValueListType",
@@ -35,7 +36,8 @@ sap.ui.define([
35
36
  ], function (Log, uid, UriParameters, ColumnListItem, CustomListItem, FlexBox, _MessageStrip, Text,
36
37
  Device, EventProvider, SyncPromise, Configuration, Controller, View, ChangeReason, Filter,
37
38
  FilterOperator, FilterType, Sorter, OperationMode, AnnotationHelper, ODataListBinding,
38
- ODataModel, ODataPropertyBinding, ValueListType, _Helper, TestUtils, XMLHelper) {
39
+ ODataMetaModel, ODataModel, ODataPropertyBinding, ValueListType, _Helper, TestUtils,
40
+ XMLHelper) {
39
41
  /*eslint no-sparse-arrays: 0, "max-len": ["error", {"code": 100,
40
42
  "ignorePattern": "/sap/opu/odata4/|\" :$|\" : \\{$|\\{meta>"}], */
41
43
  "use strict";
@@ -96,7 +98,7 @@ sap.ui.define([
96
98
  * @param {string} sTitle - A test title
97
99
  * @param {object} assert - The QUnit assert object
98
100
  * @param {sap.m.Table|sap.ui.table.Table} oTable - A table
99
- * @param {string[]} aExpectedPaths - List of all expected current conntext paths
101
+ * @param {string[]} aExpectedPaths - List of all expected (normalized) current context paths
100
102
  * @param {any[][]} aExpectedContent - "Table" of expected cell contents
101
103
  * @param {number} [iExpectedLength=aExpectedPaths.length] - Expected length
102
104
  */
@@ -108,7 +110,8 @@ sap.ui.define([
108
110
  assert.strictEqual(oListBinding.isLengthFinal(), true, "length is final");
109
111
  assert.strictEqual(oListBinding.getLength(), iExpectedLength || aExpectedPaths.length,
110
112
  sTitle);
111
- assert.deepEqual(oListBinding.getAllCurrentContexts().map(getPath), aExpectedPaths);
113
+ assert.deepEqual(oListBinding.getAllCurrentContexts().map(getNormalizedPath),
114
+ aExpectedPaths);
112
115
 
113
116
  aExpectedContent = aExpectedContent.map(function (aTexts) {
114
117
  return aTexts.map(function (vText) {
@@ -2293,6 +2296,8 @@ sap.ui.define([
2293
2296
 
2294
2297
  //*********************************************************************************************
2295
2298
  // verify that error responses are processed correctly for change sets
2299
+ //
2300
+ // ...even if 1st change set fails and 2nd contains more than one request (BCP: 2380075648)
2296
2301
  QUnit.test("error response: $batch w/ change set (framework test)", function (assert) {
2297
2302
  var oModel = this.createSalesOrdersModel(),
2298
2303
  sView = '\
@@ -2308,12 +2313,13 @@ sap.ui.define([
2308
2313
  this.expectRequest("SalesOrderList?$skip=0&$top=100", {
2309
2314
  value : [
2310
2315
  {SalesOrderID : "1", Note : "Note 1"},
2311
- {SalesOrderID : "2", Note : "Note 2"}
2316
+ {SalesOrderID : "2", Note : "Note 2"},
2317
+ {SalesOrderID : "3", Note : "Note 3"}
2312
2318
  ]
2313
2319
  })
2314
2320
  .expectRequest("BusinessPartnerList('1')/CompanyName", {value : "SAP SE"})
2315
- .expectChange("id", ["1", "2"])
2316
- .expectChange("note", ["Note 1", "Note 2"])
2321
+ .expectChange("id", ["1", "2", "3"])
2322
+ .expectChange("note", ["Note 1", "Note 2", "Note 3"])
2317
2323
  .expectChange("name", "SAP SE");
2318
2324
 
2319
2325
  return this.createView(assert, sView, oModel).then(function () {
@@ -2329,10 +2335,12 @@ sap.ui.define([
2329
2335
  .withArgs("Failed to update path /SalesOrderList('1')/Note");
2330
2336
  that.oLogMock.expects("error")
2331
2337
  .withArgs("Failed to update path /SalesOrderList('2')/Note");
2338
+ that.oLogMock.expects("error")
2339
+ .withArgs("Failed to update path /SalesOrderList('3')/Note");
2332
2340
  that.oLogMock.expects("error")
2333
2341
  .withArgs("Failed to read path /BusinessPartnerList('1')/CompanyName");
2334
2342
 
2335
- that.expectChange("note", ["Note 1 changed", "Note 2 changed"])
2343
+ that.expectChange("note", ["Note 1 changed", "Note 2 changed", "Note 3 changed"])
2336
2344
  .expectRequest({
2337
2345
  changeSetNo : 1,
2338
2346
  method : "PATCH",
@@ -2340,11 +2348,17 @@ sap.ui.define([
2340
2348
  payload : {Note : "Note 1 changed"}
2341
2349
  }, oError)
2342
2350
  .expectRequest({
2343
- changeSetNo : 1,
2351
+ changeSetNo : 2,
2344
2352
  method : "PATCH",
2345
2353
  url : "SalesOrderList('2')",
2346
2354
  payload : {Note : "Note 2 changed"}
2347
2355
  }) // no response required
2356
+ .expectRequest({
2357
+ changeSetNo : 2,
2358
+ method : "PATCH",
2359
+ url : "SalesOrderList('3')",
2360
+ payload : {Note : "Note 3 changed"}
2361
+ }) // no response required
2348
2362
  .expectRequest("BusinessPartnerList('1')/CompanyName") // no response required
2349
2363
  .expectChange("name", null)
2350
2364
  .expectMessages([{
@@ -2361,7 +2375,9 @@ sap.ui.define([
2361
2375
  }]);
2362
2376
 
2363
2377
  aTableRows[0].getCells()[1].getBinding("value").setValue("Note 1 changed");
2378
+ oModel.submitBatch(oModel.getGroupId()); // close 1st change set
2364
2379
  aTableRows[1].getCells()[1].getBinding("value").setValue("Note 2 changed");
2380
+ aTableRows[2].getCells()[1].getBinding("value").setValue("Note 3 changed");
2365
2381
  that.oView.byId("name").getBinding("text").refresh();
2366
2382
 
2367
2383
  return that.waitForChanges(assert);
@@ -3579,19 +3595,24 @@ sap.ui.define([
3579
3595
  // Scenario: ODLB, late property. See that it is requested only once, even when bound twice. See
3580
3596
  // that it is updated via requestSideEffects called at the parent binding (all visible rows).
3581
3597
  // JIRA: CPOUI5UISERVICESV3-1878
3582
- // JIRA: CPOUI5ODATAV4-23 see that a late property for a nested entity (within $expand) is
3583
- // fetched
3584
- // JIRA: CPOUI5ODATAV4-27 see that two late property requests are merged
3585
- // BCP: 2070470932: see that sap-client and system query options are handled properly
3586
- // Test ODLB#getCount
3587
- // JIRA: CPOUI5ODATAV4-958
3588
- // JIRA: CPOUI5ODATAV4-1671: See that dataRequested/dataReceived events are fired for late
3589
- // property requests
3590
- // JIRA: CPOUI5ODATAV4-1746 See that every GET request for late property requests is causing
3591
- // dataRequested/dataReceived events. The additional GET request for late properties
3592
- // is achieved by requesting an additional entity with the path
3593
- // "TEAMS('1')/TEAM_2_EMPLOYEES('3')". The path from the GET request is attached to the event
3594
- // parameter, no matter whether the request failed or succeeded.
3598
+ //
3599
+ // See that a late property for a nested entity (within $expand) is fetched
3600
+ // JIRA: CPOUI5ODATAV4-23
3601
+ //
3602
+ // See that two late property requests are merged (JIRA: CPOUI5ODATAV4-27)
3603
+ // See that sap-client and system query options are handled properly (BCP: 2070470932)
3604
+ // Test ODLB#getCount (JIRA: CPOUI5ODATAV4-958)
3605
+ //
3606
+ // See that dataRequested/dataReceived events are fired for late property requests
3607
+ // JIRA: CPOUI5ODATAV4-1671
3608
+ //
3609
+ // See that every GET request for late property requests is causing dataRequested/dataReceived
3610
+ // events. The additional GET request for late properties is achieved by requesting an
3611
+ // additional item with ItemPosition "20". The path from the GET request is attached to the
3612
+ // event parameter, no matter whether the request failed or succeeded.
3613
+ // JIRA: CPOUI5ODATAV4-1746
3614
+ //
3615
+ // Rewritten to use SalesOrder instead of TEAM (JIRA: CPOUI5ODATAV4-2172)
3595
3616
  QUnit.test("ODLB: late property", function (assert) {
3596
3617
  var bChange = false,
3597
3618
  iDataReceived = 0,
@@ -3601,66 +3622,70 @@ sap.ui.define([
3601
3622
  oRowContext,
3602
3623
  oTable,
3603
3624
  sView = '\
3604
- <FlexBox id="form" binding="{/TEAMS(\'1\')}">\
3625
+ <FlexBox id="form" binding="{/SalesOrderList(\'1\')}">\
3605
3626
  <Table id="table" growing="true" growingThreshold="2"\
3606
- items="{path : \'TEAM_2_EMPLOYEES\', parameters : {$$ownRequest : true,\
3607
- $search : \'foo\', $select : \'__CT__FAKE__Message/__FAKE__Messages\'}}">\
3608
- <Text id="name" text="{Name}"/>\
3609
- <Text id="manager" text="{EMPLOYEE_2_MANAGER/ID}"/>\
3627
+ items="{path : \'SO_2_SOITEM\', \
3628
+ parameters : {$$ownRequest : true, $search : \'foo\', $select : \'Messages\'}}">\
3629
+ <Text id="note" text="{Note}"/>\
3630
+ <Text id="scheduleKey" text="{SOITEM_2_SCHDL/ScheduleKey}"/>\
3610
3631
  </Table>\
3611
3632
  </FlexBox>\
3612
- <Input id="age1" value="{AGE}"/>\
3613
- <Text id="age2" text="{AGE}"/>\
3614
- <Input id="team" value="{EMPLOYEE_2_TEAM/TEAM_2_MANAGER/TEAM_ID}"/>\
3615
- <Input id="budget" value="{EMPLOYEE_2_TEAM/Budget}"/>',
3633
+ <Input id="unit1" value="{QuantityUnit}"/>\
3634
+ <Text id="unit2" text="{QuantityUnit}"/>\
3635
+ <Input id="bp" value="{SOITEM_2_PRODUCT/PRODUCT_2_BP/CompanyName}"/>',
3616
3636
  that = this;
3617
3637
 
3618
- oModel = this.createModel(sTeaBusi + "?sap-client=123", {autoExpandSelect : true}, {
3619
- "/sap/opu/odata4/IWBEP/TEA/default/IWBEP/TEA_BUSI/0001/$metadata?sap-client=123"
3620
- : {source : "odata/v4/data/metadata.xml"}
3638
+ oModel = this.createModel(sSalesOrderService + "?sap-client=123", {
3639
+ autoExpandSelect : true
3640
+ }, {
3641
+ "/sap/opu/odata4/sap/zui5_testv4/default/sap/zui5_epm_sample/0002/$metadata?sap-client=123"
3642
+ : {source : "odata/v4/data/metadata_zui5_epm_sample.xml"}
3621
3643
  });
3622
3644
 
3623
- this.expectRequest("TEAMS('1')/TEAM_2_EMPLOYEES?sap-client=123&$search=foo"
3624
- + "&$select=ID,Name,__CT__FAKE__Message/__FAKE__Messages"
3625
- + "&$expand=EMPLOYEE_2_MANAGER($select=ID)&$skip=0&$top=2", {
3645
+ this.expectRequest("SalesOrderList('1')/SO_2_SOITEM?sap-client=123&$search=foo"
3646
+ + "&$select=ItemPosition,Messages,Note,SalesOrderID"
3647
+ + "&$expand=SOITEM_2_SCHDL($select=ScheduleKey)&$skip=0&$top=2", {
3626
3648
  value : [{
3627
3649
  "@odata.etag" : "etag0",
3628
- ID : "2",
3629
- Name : "Frederic Fall",
3630
- EMPLOYEE_2_MANAGER : {ID : "5"}
3650
+ ItemPosition : "10",
3651
+ Messages : [],
3652
+ Note : "Note #10",
3653
+ SalesOrderID : "1",
3654
+ SOITEM_2_SCHDL : {ScheduleKey : "Key #10"}
3631
3655
  }, {
3632
3656
  "@odata.etag" : "etag0",
3633
- ID : "3",
3634
- Name : "Jonathan Smith",
3635
- EMPLOYEE_2_MANAGER : {ID : "5"}
3657
+ ItemPosition : "20",
3658
+ Messages : [],
3659
+ Note : "Note #20",
3660
+ SalesOrderID : "1",
3661
+ SOITEM_2_SCHDL : {ScheduleKey : "Key #20"}
3636
3662
  }]
3637
3663
  })
3638
- .expectChange("name", ["Frederic Fall", "Jonathan Smith"])
3639
- .expectChange("manager", ["5", "5"])
3640
- .expectChange("age1")
3641
- .expectChange("age2")
3642
- .expectChange("team")
3643
- .expectChange("budget");
3664
+ .expectChange("note", ["Note #10", "Note #20"])
3665
+ .expectChange("scheduleKey", ["Key #10", "Key #20"])
3666
+ .expectChange("unit1")
3667
+ .expectChange("unit2")
3668
+ .expectChange("bp");
3644
3669
 
3645
3670
  return this.createView(assert, sView, oModel).then(function () {
3646
- var oTeam = that.oView.byId("team");
3671
+ var oBusinessPartner = that.oView.byId("bp");
3647
3672
 
3648
3673
  oTable = that.oView.byId("table");
3649
- oTeam.getBinding("value").attachEventOnce("change", function (oEvent) {
3674
+ oBusinessPartner.getBinding("value").attachEventOnce("change", function (oEvent) {
3650
3675
  bChange = true;
3651
- assert.strictEqual(oEvent.getSource().getValue(), "1");
3652
- assert.strictEqual(oTeam.getValue(), "1");
3676
+ assert.strictEqual(oEvent.getSource().getValue(), "ACM");
3677
+ assert.strictEqual(oBusinessPartner.getValue(), "ACM");
3653
3678
  });
3654
3679
  oModel.attachDataRequested(function (oEvent) {
3655
3680
  sPath = oEvent.getParameter("path");
3656
3681
 
3657
3682
  iDataRequested += 1;
3658
3683
  if (iDataRequested === 1) {
3659
- assert.strictEqual(sPath, "/TEAMS('1')/TEAM_2_EMPLOYEES('2')");
3684
+ assert.strictEqual(sPath,
3685
+ "/SalesOrderList('1')/SO_2_SOITEM(SalesOrderID='1',ItemPosition='10')");
3660
3686
  } else if (iDataRequested === 2) {
3661
- assert.strictEqual(sPath, "/TEAMS('1')/TEAM_2_EMPLOYEES('3')");
3662
- } else if (iDataRequested === 3) {
3663
- assert.strictEqual(sPath, "/TEAMS('1')/TEAM_2_EMPLOYEES('2')/EMPLOYEE_2_TEAM");
3687
+ assert.strictEqual(sPath,
3688
+ "/SalesOrderList('1')/SO_2_SOITEM(SalesOrderID='1',ItemPosition='20')");
3664
3689
  }
3665
3690
  }).attachDataReceived(function (oEvent) {
3666
3691
  sPath = oEvent.getParameter("path");
@@ -3669,13 +3694,13 @@ sap.ui.define([
3669
3694
  assert.deepEqual(oEvent.getParameter("data"), {});
3670
3695
 
3671
3696
  if (iDataReceived === 1) {
3672
- assert.strictEqual(sPath, "/TEAMS('1')/TEAM_2_EMPLOYEES('3')");
3697
+ assert.strictEqual(sPath,
3698
+ "/SalesOrderList('1')/SO_2_SOITEM(SalesOrderID='1',ItemPosition='20')");
3673
3699
  assert.strictEqual(bChange, false, "change event not yet fired");
3674
3700
  } else if (iDataReceived === 2) {
3675
- assert.strictEqual(sPath, "/TEAMS('1')/TEAM_2_EMPLOYEES('2')");
3701
+ assert.strictEqual(sPath,
3702
+ "/SalesOrderList('1')/SO_2_SOITEM(SalesOrderID='1',ItemPosition='10')");
3676
3703
  assert.strictEqual(bChange, true, "fired after change event");
3677
- } else if (iDataReceived === 3) {
3678
- assert.strictEqual(sPath, "/TEAMS('1')/TEAM_2_EMPLOYEES('2')/EMPLOYEE_2_TEAM");
3679
3704
  }
3680
3705
  });
3681
3706
 
@@ -3685,53 +3710,55 @@ sap.ui.define([
3685
3710
 
3686
3711
  that.expectRequest({
3687
3712
  batchNo : 2,
3688
- url : "TEAMS('1')/TEAM_2_EMPLOYEES('2')?sap-client=123"
3689
- + "&$select=AGE&$expand=EMPLOYEE_2_TEAM($select=Team_Id;"
3690
- + "$expand=TEAM_2_MANAGER($select=ID,TEAM_ID))"
3713
+ url : "SalesOrderList('1')/SO_2_SOITEM(SalesOrderID='1',ItemPosition='10')"
3714
+ + "?sap-client=123"
3715
+ + "&$select=QuantityUnit&$expand=SOITEM_2_PRODUCT($select=ProductID;"
3716
+ + "$expand=PRODUCT_2_BP($select=BusinessPartnerID,CompanyName))"
3691
3717
  }, {
3692
3718
  "@odata.etag" : "etag0",
3693
- AGE : 42,
3694
- EMPLOYEE_2_TEAM : {
3719
+ QuantityUnit : "kg",
3720
+ SOITEM_2_PRODUCT : {
3695
3721
  "@odata.etag" : "etag1",
3696
- Team_Id : "1",
3697
- TEAM_2_MANAGER : {
3722
+ ProductID : "3",
3723
+ PRODUCT_2_BP : {
3698
3724
  "@odata.etag" : "ETag",
3699
- ID : "5",
3700
- TEAM_ID : "1"
3725
+ BusinessPartnerID : "4",
3726
+ CompanyName : "ACM"
3701
3727
  }
3702
3728
  }
3703
3729
  })
3704
3730
  // the additional late property request
3705
3731
  .expectRequest({
3706
3732
  batchNo : 2,
3707
- url : "TEAMS('1')/TEAM_2_EMPLOYEES('3')?sap-client=123"
3708
- + "&$select=EMPLOYEE_2_TEAM&$expand=EMPLOYEE_2_TEAM($select=Team_Id;"
3709
- + "$expand=TEAM_2_MANAGER($select=ID,TEAM_ID))"
3733
+ url : "SalesOrderList('1')/SO_2_SOITEM(SalesOrderID='1',ItemPosition='20')"
3734
+ + "?sap-client=123"
3735
+ + "&$select=SOITEM_2_PRODUCT&$expand=SOITEM_2_PRODUCT($select=ProductID;"
3736
+ + "$expand=PRODUCT_2_BP($select=BusinessPartnerID,CompanyName))"
3710
3737
  }, {
3711
3738
  "@odata.etag" : "etag0",
3712
- EMPLOYEE_2_TEAM : {
3739
+ SOITEM_2_PRODUCT : {
3713
3740
  "@odata.etag" : "etag1",
3714
- Team_Id : "1",
3715
- TEAM_2_MANAGER : {
3741
+ ProductID : "3",
3742
+ PRODUCT_2_BP : {
3716
3743
  "@odata.etag" : "ETag",
3717
- ID : "5",
3718
- TEAM_ID : "1"
3744
+ BusinessPartnerID : "4",
3745
+ CompanyName : "ACM"
3719
3746
  }
3720
3747
  }
3721
3748
  })
3722
- .expectChange("age1", "42")
3723
- .expectChange("team", "1");
3749
+ .expectChange("unit1", "kg")
3750
+ .expectChange("bp", "ACM");
3724
3751
 
3725
- // code under test - AGE and Team_Id are requested
3752
+ // code under test - QuantityUnit and CompanyName are requested
3726
3753
  oRowContext = oTable.getItems()[0].getBindingContext();
3727
- that.oView.byId("age1").setBindingContext(oRowContext);
3728
- that.oView.byId("team").setBindingContext(oRowContext);
3754
+ that.oView.byId("unit1").setBindingContext(oRowContext);
3755
+ that.oView.byId("bp").setBindingContext(oRowContext);
3729
3756
 
3730
3757
  return Promise.all([
3731
3758
  // the additional late property request for a *different* row
3732
3759
  // JIRA: CPOUI5ODATAV4-1746
3733
3760
  oTable.getItems()[1].getBindingContext()
3734
- .requestProperty("EMPLOYEE_2_TEAM/TEAM_2_MANAGER/TEAM_ID"),
3761
+ .requestProperty("SOITEM_2_PRODUCT/PRODUCT_2_BP/CompanyName"),
3735
3762
  that.waitForChanges(assert)
3736
3763
  ]);
3737
3764
  }).then(function () {
@@ -3739,164 +3766,160 @@ sap.ui.define([
3739
3766
  assert.strictEqual(iDataReceived, 2);
3740
3767
 
3741
3768
  // BCP 1980517597
3742
- that.expectChange("age1", "18")
3769
+ that.expectChange("unit1", "t")
3743
3770
  .expectRequest({
3744
3771
  method : "PATCH",
3745
3772
  headers : {"If-Match" : "etag0"},
3746
- url : "EMPLOYEES('2')?sap-client=123",
3747
- payload : {AGE : 18}
3773
+ url : "SalesOrderList('1')/SO_2_SOITEM(SalesOrderID='1',ItemPosition='10')"
3774
+ + "?sap-client=123",
3775
+ payload : {QuantityUnit : "t"}
3748
3776
  }, {
3749
3777
  "@odata.etag" : "etag23",
3750
3778
  AGE : 18,
3751
- __CT__FAKE__Message : {
3752
- __FAKE__Messages : [{
3753
- code : "1",
3754
- message : "That is very young",
3755
- numericSeverity : 3,
3756
- target : "AGE",
3757
- transition : false
3758
- }]
3759
- }
3779
+ Messages : [{
3780
+ code : "1",
3781
+ message : "Are you sure?",
3782
+ numericSeverity : 3,
3783
+ target : "QuantityUnit",
3784
+ transition : false
3785
+ }]
3760
3786
  })
3761
3787
  .expectMessages([{
3762
3788
  code : "1",
3763
- message : "That is very young",
3764
- target : "/TEAMS('1')/TEAM_2_EMPLOYEES('2')/AGE",
3789
+ message : "Are you sure?",
3790
+ target : "/SalesOrderList('1')/SO_2_SOITEM(SalesOrderID='1',ItemPosition='10')"
3791
+ + "/QuantityUnit",
3765
3792
  type : "Warning"
3766
3793
  }]);
3767
3794
 
3768
3795
  // code under test
3769
- that.oView.byId("age1").getBinding("value").setValue(18);
3796
+ that.oView.byId("unit1").getBinding("value").setValue("t");
3770
3797
 
3771
3798
  return that.waitForChanges(assert);
3772
3799
  }).then(function () {
3773
- return that.checkValueState(assert, "age1", "Warning", "That is very young");
3800
+ return that.checkValueState(assert, "unit1", "Warning", "Are you sure?");
3774
3801
  }).then(function () {
3775
- that.expectChange("team", "changed")
3802
+ that.expectChange("bp", "changed")
3776
3803
  .expectRequest({
3777
3804
  method : "PATCH",
3778
3805
  headers : {"If-Match" : "ETag"},
3779
- url : "MANAGERS('5')?sap-client=123",
3780
- payload : {TEAM_ID : "changed"}
3806
+ url : "BusinessPartnerList('4')?sap-client=123",
3807
+ payload : {CompanyName : "changed"}
3781
3808
  });
3782
3809
 
3783
3810
  // code under test
3784
- that.oView.byId("team").getBinding("value").setValue("changed");
3811
+ that.oView.byId("bp").getBinding("value").setValue("changed");
3785
3812
 
3786
3813
  return that.waitForChanges(assert);
3787
3814
  }).then(function () {
3788
3815
  assert.strictEqual(iDataRequested, 2);
3789
3816
  assert.strictEqual(iDataReceived, 2);
3790
3817
 
3791
- that.expectRequest("TEAMS('1')/TEAM_2_EMPLOYEES('2')/EMPLOYEE_2_TEAM?sap-client=123"
3792
- + "&$select=Budget,Team_Id", {
3793
- "@odata.etag" : "etag1",
3794
- Budget : "12.45",
3795
- Team_Id : "1"
3796
- })
3797
- .expectChange("budget", "12.45");
3818
+ that.expectChange("unit2", "t");
3798
3819
 
3799
- // code under test - now the team is in the cache and only the budget is missing
3800
- that.oView.byId("budget").setBindingContext(oRowContext);
3820
+ // code under test - QuantityUnit is cached now
3821
+ that.oView.byId("unit2").setBindingContext(oRowContext);
3801
3822
 
3802
3823
  return that.waitForChanges(assert);
3803
3824
  }).then(function () {
3804
- assert.strictEqual(iDataRequested, 3);
3805
- assert.strictEqual(iDataReceived, 3);
3806
-
3807
- that.expectChange("age2", "18");
3808
-
3809
- // code under test - AGE is cached now
3810
- that.oView.byId("age2").setBindingContext(oRowContext);
3811
-
3812
- return that.waitForChanges(assert);
3813
- }).then(function () {
3814
- that.expectRequest("TEAMS('1')/TEAM_2_EMPLOYEES?sap-client=123&$search=foo"
3815
- + "&$select=ID,Name,__CT__FAKE__Message/__FAKE__Messages"
3816
- + "&$expand=EMPLOYEE_2_MANAGER($select=ID)&$skip=2&$top=2", {
3817
- value : [
3818
- {ID : "4", Name : "Peter Burke", EMPLOYEE_2_MANAGER : {ID : "5"}}
3819
- ]
3825
+ that.expectRequest("SalesOrderList('1')/SO_2_SOITEM?sap-client=123&$search=foo"
3826
+ + "&$select=ItemPosition,Messages,Note,SalesOrderID"
3827
+ + "&$expand=SOITEM_2_SCHDL($select=ScheduleKey)&$skip=2&$top=2", {
3828
+ value : [{
3829
+ ItemPosition : "30",
3830
+ Messages : [],
3831
+ Note : "Note #30",
3832
+ SalesOrderID : "1",
3833
+ SOITEM_2_SCHDL : {ScheduleKey : "Key #30"}
3834
+ }]
3820
3835
  })
3821
- .expectChange("name", [,, "Peter Burke"])
3822
- .expectChange("manager", [,, "5"]);
3836
+ .expectChange("note", [,, "Note #30"])
3837
+ .expectChange("scheduleKey", [,, "Key #30"]);
3823
3838
 
3824
- // code under test - AGE must not be requested when paging
3839
+ // code under test - QuantityUnit must not be requested when paging
3825
3840
  oTable.requestItems();
3826
3841
 
3827
3842
  return that.waitForChanges(assert);
3828
3843
  }).then(function () {
3829
- assert.strictEqual(iDataRequested, 4, "bubbled up from the binding");
3830
- assert.strictEqual(iDataReceived, 4, "bubbled up from the binding");
3844
+ assert.strictEqual(iDataRequested, 3, "bubbled up from the binding");
3845
+ assert.strictEqual(iDataReceived, 3, "bubbled up from the binding");
3831
3846
 
3832
- that.expectRequest("TEAMS('1')/TEAM_2_EMPLOYEES?sap-client=123&$select=AGE,ID,Name"
3833
- + "&$filter=ID eq '2' or ID eq '3' or ID eq '4'&$top=3", {
3847
+ that.expectRequest("SalesOrderList('1')/SO_2_SOITEM?sap-client=123"
3848
+ + "&$select=ItemPosition,Note,QuantityUnit,SalesOrderID"
3849
+ + "&$filter=SalesOrderID eq '1' and ItemPosition eq '10' or SalesOrderID eq '1'"
3850
+ + " and ItemPosition eq '20' or SalesOrderID eq '1' and ItemPosition eq '30'"
3851
+ + "&$top=3", {
3834
3852
  value : [
3835
- {AGE : 43, ID : "2", Name : "Frederic Fall *"},
3836
- {AGE : 29, ID : "3", Name : "Jonathan Smith *"},
3837
- {AGE : 0, ID : "4", Name : "Peter Burke *"}
3853
+ {ItemPosition : "10", Note : "#1", QuantityUnit : "g", SalesOrderID : "1"},
3854
+ {ItemPosition : "20", Note : "#2", QuantityUnit : "dz", SalesOrderID : "1"},
3855
+ {ItemPosition : "30", Note : "#3", QuantityUnit : "g", SalesOrderID : "1"}
3838
3856
  ]
3839
3857
  })
3840
- .expectChange("age1", "43")
3841
- .expectChange("age2", "43")
3842
- .expectChange("name", ["Frederic Fall *", "Jonathan Smith *", "Peter Burke *"]);
3858
+ .expectChange("unit1", "g")
3859
+ .expectChange("unit2", "g")
3860
+ .expectChange("note", ["#1", "#2", "#3"]);
3843
3861
 
3844
- // see that requestSideEffects updates AGE, too
3862
+ // see that requestSideEffects updates QuantityUnit, too
3845
3863
  return Promise.all([
3846
- oTable.getBinding("items").getHeaderContext().requestSideEffects(["AGE", "Name"]),
3864
+ oTable.getBinding("items").getHeaderContext()
3865
+ .requestSideEffects(["Note", "QuantityUnit"]),
3847
3866
  that.waitForChanges(assert)
3848
3867
  ]);
3849
3868
  }).then(function () {
3850
- assert.strictEqual(iDataRequested, 4);
3851
- assert.strictEqual(iDataReceived, 4);
3869
+ assert.strictEqual(iDataRequested, 3);
3870
+ assert.strictEqual(iDataReceived, 3);
3852
3871
 
3853
- that.expectChange("age2", "29");
3872
+ that.expectChange("unit2", "dz");
3854
3873
 
3855
3874
  // change one Text to the second row - must be cached from requestSideEffects
3856
3875
  oRowContext = oTable.getItems()[1].getBindingContext();
3857
- that.oView.byId("age2").setBindingContext(oRowContext);
3876
+ that.oView.byId("unit2").setBindingContext(oRowContext);
3858
3877
 
3859
3878
  return that.waitForChanges(assert);
3860
3879
  }).then(function () {
3861
- assert.strictEqual(iDataRequested, 4);
3862
- assert.strictEqual(iDataReceived, 4);
3880
+ assert.strictEqual(iDataRequested, 3);
3881
+ assert.strictEqual(iDataReceived, 3);
3863
3882
 
3864
- that.expectRequest("TEAMS('1')/TEAM_2_EMPLOYEES?sap-client=123&$select=AGE,ID,Name"
3865
- + "&$filter=ID eq '2' or ID eq '3' or ID eq '4'&$top=3", {
3883
+ that.expectRequest("SalesOrderList('1')/SO_2_SOITEM?sap-client=123"
3884
+ + "&$select=ItemPosition,Note,QuantityUnit,SalesOrderID"
3885
+ + "&$filter=SalesOrderID eq '1' and ItemPosition eq '10' or SalesOrderID eq '1'"
3886
+ + " and ItemPosition eq '20' or SalesOrderID eq '1' and ItemPosition eq '30'"
3887
+ + "&$top=3", {
3866
3888
  value : [
3867
- {AGE : 44, ID : "2", Name : "Frederic Fall **"},
3868
- {AGE : 30, ID : "3", Name : "Jonathan Smith **"},
3869
- {AGE : -1, ID : "4", Name : "Peter Burke **"}
3889
+ {ItemPosition : "10", Note : "$1", QuantityUnit : "ou", SalesOrderID : "1"},
3890
+ {ItemPosition : "20", Note : "$2", QuantityUnit : "t", SalesOrderID : "1"},
3891
+ {ItemPosition : "30", Note : "$3", QuantityUnit : "?", SalesOrderID : "1"}
3870
3892
  ]
3871
3893
  })
3872
- .expectChange("age1", "44")
3873
- .expectChange("age2", "30")
3874
- .expectChange("name", ["Frederic Fall **", "Jonathan Smith **", "Peter Burke **"]);
3894
+ .expectChange("unit1", "ou")
3895
+ .expectChange("unit2", "t")
3896
+ .expectChange("note", ["$1", "$2", "$3"]);
3875
3897
 
3876
3898
  return Promise.all([
3877
3899
  // code under test: requestSideEffects on ODCB w/o data
3878
3900
  that.oView.byId("form").getBindingContext().requestSideEffects([
3879
- {$PropertyPath : "TEAM_2_EMPLOYEES/AGE"},
3880
- {$PropertyPath : "TEAM_2_EMPLOYEES/Name"}
3901
+ {$PropertyPath : "SO_2_SOITEM/QuantityUnit"},
3902
+ {$PropertyPath : "SO_2_SOITEM/Note"}
3881
3903
  ]),
3882
3904
  that.waitForChanges(assert)
3883
3905
  ]);
3884
3906
  }).then(function () {
3885
- assert.strictEqual(iDataRequested, 4);
3886
- assert.strictEqual(iDataReceived, 4);
3907
+ assert.strictEqual(iDataRequested, 3);
3908
+ assert.strictEqual(iDataReceived, 3);
3887
3909
 
3888
- that.expectRequest("TEAMS('1')/TEAM_2_EMPLOYEES('3')?sap-client=123&$select=TEAM_ID",
3889
- {"@odata.etag" : "etag0", TEAM_ID : "1"});
3910
+ that.expectRequest("SalesOrderList('1')/SO_2_SOITEM(SalesOrderID='1',ItemPosition='20')"
3911
+ + "?sap-client=123&$select=CurrencyCode",
3912
+ {"@odata.etag" : "etag0", CurrencyCode : "USD"});
3890
3913
 
3891
3914
  return Promise.all([
3892
- oRowContext.requestProperty("TEAM_ID").then(function (sTeamId) {
3893
- assert.strictEqual(sTeamId, "1");
3915
+ oRowContext.requestProperty("CurrencyCode").then(function (sCurrencyCode) {
3916
+ assert.strictEqual(sCurrencyCode, "USD");
3894
3917
  }),
3895
3918
  that.waitForChanges(assert)
3896
3919
  ]);
3897
3920
  }).then(function () {
3898
- assert.strictEqual(iDataRequested, 5);
3899
- assert.strictEqual(iDataReceived, 5);
3921
+ assert.strictEqual(iDataRequested, 4);
3922
+ assert.strictEqual(iDataReceived, 4);
3900
3923
  });
3901
3924
  });
3902
3925
 
@@ -5211,7 +5234,9 @@ sap.ui.define([
5211
5234
  return Promise.all([
5212
5235
  Promise.resolve().then(function () {
5213
5236
  // code under test
5214
- oTable.destroy();
5237
+ // Note: oTable.destroy(); not allowed for direct children of XMLView!
5238
+ that.oView.destroy();
5239
+ delete that.oView;
5215
5240
  }),
5216
5241
  that.waitForChanges(assert)
5217
5242
  ]);
@@ -7289,17 +7314,17 @@ sap.ui.define([
7289
7314
  {reason : "refresh"}],
7290
7315
  ["ContextBinding: /SalesOrderList('0500000001')", "change",
7291
7316
  {reason : "refresh"}],
7292
- ["ContextBinding: /SalesOrderList('0500000001')", "dataRequested"],
7293
7317
  ["ListBinding: /SalesOrderList('0500000001')|SO_2_SOITEM", "dataRequested"],
7318
+ ["ContextBinding: /SalesOrderList('0500000001')", "dataRequested"],
7294
7319
  ["ContextBinding: /SalesOrderList('0500000001')", "dataReceived", {data : {}}],
7295
7320
  ["ListBinding: /SalesOrderList('0500000001')|SO_2_SOITEM", "change",
7296
7321
  {reason : "change"}],
7297
7322
  ["ListBinding: /SalesOrderList('0500000001')|SO_2_SOITEM", "dataReceived",
7298
7323
  {data : {}}],
7299
- ["PropertyBinding: /SalesOrderList('0500000001')|Note", "change",
7300
- {reason : "refresh"}],
7301
7324
  ["PropertyBinding: /SalesOrderList('0500000001')/SO_2_SOITEM|$count", "change",
7302
7325
  {reason : "change"}],
7326
+ ["PropertyBinding: /SalesOrderList('0500000001')|Note", "change",
7327
+ {reason : "refresh"}],
7303
7328
  ["PropertyBinding: /SalesOrderList('0500000001')/SO_2_SOITEM/2[2]|ItemPosition",
7304
7329
  "change", {reason : "change"}]
7305
7330
  ])
@@ -7331,7 +7356,7 @@ sap.ui.define([
7331
7356
  // BCP: 2270183841
7332
7357
  QUnit.test("BCP: 2270183841 - improve performance of ODLB#resume", function (assert) {
7333
7358
  var oModel = this.createTeaBusiModel({autoExpandSelect : true}),
7334
- fnSpy = sinon.spy(ODataPropertyBinding.prototype, "resumeInternal"),
7359
+ fnSpy = this.spy(ODataPropertyBinding.prototype, "resumeInternal"),
7335
7360
  sView = '\
7336
7361
  <t:Table id="table" rows="{/EMPLOYEES}" threshold="0" visibleRowCount="3">\
7337
7362
  <Text id="id" text="{ID}"/>\
@@ -7377,6 +7402,167 @@ sap.ui.define([
7377
7402
  });
7378
7403
  });
7379
7404
 
7405
+ //*********************************************************************************************
7406
+ // Scenario: A table shows a number of cells and then we scroll down. See that property bindings
7407
+ // do not recompute "static" information in vain.
7408
+ // BCP: 156484 / 2023 (002075129500001564842023)
7409
+ QUnit.test("BCP: 156484 / 2023 - improve performance of ODPrB#setContext", function (assert) {
7410
+ var fnSpy_ODMM_fetchUI5Type = this.spy(ODataMetaModel.prototype, "fetchUI5Type"),
7411
+ fnSpy_ODMM_getReducedPath = this.spy(ODataMetaModel.prototype, "getReducedPath"),
7412
+ fnSpy_ODLB_doFetchOrGetQueryOptions
7413
+ = this.spy(ODataListBinding.prototype, "doFetchOrGetQueryOptions"),
7414
+ oModel = this.createTeaBusiModel({autoExpandSelect : true}),
7415
+ sView = '\
7416
+ <t:Table id="table" rows="{/EMPLOYEES}" visibleRowCount="3">\
7417
+ <Text id="id" text="{ID}"/>\
7418
+ <Text id="name" text="{Name}"/>\
7419
+ <Text id="age" text="{path:\'AGE\',type:\'sap.ui.model.odata.type.Int16\'\
7420
+ ,formatOptions:{\'minIntegerDigits\':3}}"/>\
7421
+ </t:Table>',
7422
+ that = this;
7423
+
7424
+ this.expectRequest("EMPLOYEES?$select=AGE,ID,Name&$skip=0&$top=103", {
7425
+ value : [{
7426
+ AGE : 70,
7427
+ ID : "0",
7428
+ Name : "Frederic Fall"
7429
+ }, {
7430
+ AGE : 60,
7431
+ ID : "1",
7432
+ Name : "Jonathan Smith"
7433
+ }, {
7434
+ AGE : 50,
7435
+ ID : "2",
7436
+ Name : "Peter Burke"
7437
+ }, {
7438
+ AGE : 40,
7439
+ ID : "3",
7440
+ Name : "Carla Blue"
7441
+ }, {
7442
+ AGE : 30,
7443
+ ID : "4",
7444
+ Name : "John Field"
7445
+ }, {
7446
+ AGE : 20,
7447
+ ID : "5",
7448
+ Name : "Susan Bay"
7449
+ }]
7450
+ })
7451
+ .expectChange("id", ["0", "1", "2"])
7452
+ .expectChange("name", ["Frederic Fall", "Jonathan Smith", "Peter Burke"])
7453
+ .expectChange("age", ["070", "060", "050"])
7454
+ .expectChange("lastModifiedAt", []);
7455
+
7456
+ return this.createView(assert, sView, oModel).then(function () {
7457
+ assert.strictEqual(fnSpy_ODMM_fetchUI5Type.callCount, 6, // was: 12
7458
+ "initial #fetchUI5Type");
7459
+ assert.strictEqual(fnSpy_ODMM_getReducedPath.callCount, 3); // was: 12
7460
+ assert.strictEqual(fnSpy_ODLB_doFetchOrGetQueryOptions.callCount, 4); // was: 13
7461
+
7462
+ that.expectChange("id", [, "1", "2", "3"])
7463
+ .expectChange("name", [, "Jonathan Smith", "Peter Burke", "Carla Blue"])
7464
+ .expectChange("age", [, "060", "050", "040"]);
7465
+
7466
+ that.oView.byId("table").setFirstVisibleRow(1);
7467
+
7468
+ return that.waitForChanges(assert, "scroll down 1x");
7469
+ }).then(function () {
7470
+ assert.strictEqual(fnSpy_ODMM_fetchUI5Type.callCount, 6, "no more #fetchUI5Type");
7471
+ assert.strictEqual(fnSpy_ODMM_getReducedPath.callCount, 3); // was: 21
7472
+ assert.strictEqual(fnSpy_ODLB_doFetchOrGetQueryOptions.callCount, 4); // was: 22
7473
+
7474
+ that.expectChange("id", [,,, "3", "4", "5"])
7475
+ .expectChange("name", [,,, "Carla Blue", "John Field", "Susan Bay"])
7476
+ .expectChange("age", [,,, "040", "030", "020"]);
7477
+
7478
+ that.oView.byId("table").setFirstVisibleRow(3);
7479
+
7480
+ return that.waitForChanges(assert, "scroll down 2x");
7481
+ }).then(function () {
7482
+ assert.strictEqual(fnSpy_ODMM_fetchUI5Type.callCount, 6, "no more #fetchUI5Type");
7483
+ assert.strictEqual(fnSpy_ODMM_getReducedPath.callCount, 3); // was: 31
7484
+ assert.strictEqual(fnSpy_ODLB_doFetchOrGetQueryOptions.callCount, 4); // was: 30
7485
+ });
7486
+ });
7487
+
7488
+ //*********************************************************************************************
7489
+ // Scenario: A field shows a property where the exact type depends on the parent entity.
7490
+ // BCP: 156484 / 2023 (002075129500001564842023)
7491
+ [false, true, 1].forEach(function (bUnresolved) {
7492
+ var sTitle = "BCP: 156484 / 2023 - type depends on parent entity; unresolved in between: "
7493
+ + bUnresolved;
7494
+
7495
+ QUnit.test(sTitle, function (assert) {
7496
+ var oModel = this.createTeaBusiModel({autoExpandSelect : true}),
7497
+ oTeamContext = oModel.createBindingContext("/TEAMS('1')"),
7498
+ fnSpy = this.spy(ODataMetaModel.prototype, "fetchUI5Type"),
7499
+ oText,
7500
+ sView = '\
7501
+ <Text id="name" text="{Name}"/>', //TODO binding="{}"
7502
+ that = this;
7503
+
7504
+ this.expectChange("name");
7505
+
7506
+ return this.createView(assert, sView, oModel).then(function () {
7507
+ oText = that.oView.byId("name");
7508
+
7509
+ assert.strictEqual(fnSpy.callCount, 0, "no #fetchUI5Type yet");
7510
+
7511
+ that.expectRequest("TEAMS('1')/Name", {value : "Team #1"})
7512
+ .expectChange("name", "Team #1");
7513
+
7514
+ oText.setBindingContext(oTeamContext);
7515
+
7516
+ return that.waitForChanges(assert, "TEAMS/Name");
7517
+ }).then(function () {
7518
+ if (bUnresolved) {
7519
+ that.expectChange("name", null);
7520
+
7521
+ oText.setBindingContext(null);
7522
+
7523
+ return that.waitForChanges(assert, "unresolved");
7524
+ }
7525
+ }).then(function () {
7526
+ if (bUnresolved === 1) {
7527
+ that.expectChange("name", "Team #1");
7528
+
7529
+ oText.setBindingContext(oTeamContext);
7530
+
7531
+ return that.waitForChanges(assert, "TEAMS/Name again");
7532
+ }
7533
+ }).then(function () {
7534
+ var oType = oText.getBinding("text").getType();
7535
+
7536
+ assert.strictEqual(fnSpy.callCount, 1, "1st #fetchUI5Type");
7537
+ assert.strictEqual(oType.getConstraints().maxLength, 40,
7538
+ "Don't try this at home, kids!");
7539
+ sap.ui.test.TestUtils.withNormalizedMessages(function () {
7540
+ assert.throws(function () {
7541
+ oType.validateValue("0123456789012345678901234567890123456789+");
7542
+ }, /EnterTextMaxLength 40/);
7543
+ });
7544
+
7545
+ that.expectRequest("EMPLOYEES('0')/Name", {value : "Frederic Fall"})
7546
+ .expectChange("name", "Frederic Fall");
7547
+
7548
+ oText.setBindingContext(oModel.createBindingContext("/EMPLOYEES('0')"));
7549
+
7550
+ return that.waitForChanges(assert, "EMPLOYEES/Name");
7551
+ }).then(function () {
7552
+ var oType = oText.getBinding("text").getType();
7553
+
7554
+ assert.strictEqual(fnSpy.callCount, 2, "2nd #fetchUI5Type");
7555
+ assert.strictEqual(oType.getConstraints().maxLength, 16,
7556
+ "Don't try this at home, kids!");
7557
+ sap.ui.test.TestUtils.withNormalizedMessages(function () {
7558
+ assert.throws(function () {
7559
+ oType.validateValue("0123456789ABCDEF+");
7560
+ }, /EnterTextMaxLength 16/);
7561
+ });
7562
+ });
7563
+ });
7564
+ });
7565
+
7380
7566
  //*********************************************************************************************
7381
7567
  // Scenario: Modify a property which does not belong to the parent binding's entity, but is
7382
7568
  // related via a navigation property.
@@ -8411,7 +8597,7 @@ sap.ui.define([
8411
8597
  var oTable = that.oView.byId("table");
8412
8598
 
8413
8599
  that.expectChange("note", ["bar", "foo"])
8414
- .expectChange("companyName", [null, "SAP"])
8600
+ .expectChange("companyName", ["", "SAP"])
8415
8601
  .expectChange("buyerID", ["24", "23"])
8416
8602
  .expectChange("note", ["baz"]);
8417
8603
 
@@ -10917,11 +11103,11 @@ sap.ui.define([
10917
11103
  }]
10918
11104
  })
10919
11105
  .expectChange("city", ["Walldorf"])
10920
- .expectChange("longitude", [null]);
11106
+ .expectChange("longitude", ["0.000000000000"]); // default value
10921
11107
 
10922
11108
  return this.createView(assert, sView, oModel).then(function () {
10923
11109
  that.expectChange("city", ["", "Walldorf"])
10924
- .expectChange("longitude", ["0.000000000000", null]);
11110
+ .expectChange("longitude", [, "0.000000000000"]);
10925
11111
 
10926
11112
  oTable = that.oView.byId("table");
10927
11113
  oTable.getBinding("items").create();
@@ -18024,9 +18210,7 @@ sap.ui.define([
18024
18210
  method : "DELETE",
18025
18211
  url : "BusinessPartnerList('0100000000')"
18026
18212
  })
18027
- // Note: The value of the property binding is undefined because there is no
18028
- // explicit cache value for it, but the type's formatValue converts this to null.
18029
- .expectChange("companyName", null)
18213
+ .expectChange("companyName", "") // defaulting to null in the cache
18030
18214
  .expectChange("phoneNumber", null);
18031
18215
 
18032
18216
  return Promise.all([
@@ -19053,6 +19237,72 @@ sap.ui.define([
19053
19237
  });
19054
19238
  });
19055
19239
 
19240
+ //*********************************************************************************************
19241
+ // Scenario: Deferred delete in a nested list w/o cache. Filter in the parent list, so that the
19242
+ // parent entity drops out. Then submit or reset (canceling the delete).
19243
+ // BCP: 2380081607
19244
+ [false, true].forEach(function (bReset) {
19245
+ QUnit.test("ODLB: no cache, deferred delete, parent lost, reset=" + bReset, function (assert) {
19246
+ var oDeletePromise,
19247
+ oModel = this.createTeaBusiModel({autoExpandSelect : true, updateGroupId : "update"}),
19248
+ sView = '\
19249
+ <Table id="teams" items="{/TEAMS}">\
19250
+ <Text id="team" text="{Team_Id}"/>\
19251
+ <Table items="{path : \'TEAM_2_EMPLOYEES\', templateShareable : true}">\
19252
+ <Text id="employee" text="{ID}"/>\
19253
+ </Table>\
19254
+ </Table>',
19255
+ that = this;
19256
+
19257
+ this.expectRequest("TEAMS?$select=Team_Id&$expand=TEAM_2_EMPLOYEES($select=ID)"
19258
+ + "&$skip=0&$top=100", {
19259
+ value : [{
19260
+ Team_Id : "TEAM_1",
19261
+ TEAM_2_EMPLOYEES : [{ID : "1"}, {ID : "2"}]
19262
+ }]
19263
+ })
19264
+ .expectChange("team", ["TEAM_1"])
19265
+ .expectChange("employee", ["1", "2"]);
19266
+
19267
+ return this.createView(assert, sView, oModel).then(function () {
19268
+ that.expectChange("employee", ["2"]);
19269
+
19270
+ oDeletePromise = that.oView.byId("teams").getItems()[0].getCells()[1]
19271
+ .getBinding("items").getCurrentContexts()[0].delete();
19272
+
19273
+ return that.waitForChanges(assert);
19274
+ }).then(function () {
19275
+ that.expectRequest("TEAMS?$select=Team_Id&$expand=TEAM_2_EMPLOYEES($select=ID)"
19276
+ + "&$filter=Team_Id ne '1'&$skip=0&$top=100", {value : []});
19277
+
19278
+ that.oView.byId("teams").getBinding("items")
19279
+ .filter(new Filter("Team_Id", FilterOperator.NE, "1"));
19280
+
19281
+ return that.waitForChanges(assert);
19282
+ }).then(function () {
19283
+ if (bReset) {
19284
+ that.expectCanceledError("Failed to delete /TEAMS('TEAM_1')/TEAM_2_EMPLOYEES('1')",
19285
+ "Request canceled: DELETE EMPLOYEES('1'); group: update");
19286
+
19287
+ oModel.resetChanges();
19288
+ } else {
19289
+ that.expectRequest("DELETE EMPLOYEES('1')");
19290
+ }
19291
+
19292
+ return Promise.all([
19293
+ oModel.submitBatch("update"),
19294
+ oDeletePromise.then(function () {
19295
+ assert.notOk(bReset);
19296
+ }, function (oError) {
19297
+ assert.ok(bReset);
19298
+ assert.ok(oError.canceled);
19299
+ }),
19300
+ that.waitForChanges(assert)
19301
+ ]);
19302
+ });
19303
+ });
19304
+ });
19305
+
19056
19306
  //*********************************************************************************************
19057
19307
  // Scenario: Create and persist two contexts using "end of start". Delete one via API group and
19058
19308
  // the other one via $auto (to see that we must react on the last deletion). Create a third
@@ -19193,6 +19443,7 @@ sap.ui.define([
19193
19443
  }).then(function (aResult) {
19194
19444
  oPromise = aResult[0].delete(); // delete the RVC
19195
19445
 
19446
+ // It's not possible to synchronously reset after delete, so wait a short moment.
19196
19447
  return that.waitForChanges(assert, "deferred delete");
19197
19448
  }).then(function () {
19198
19449
  that.expectCanceledError(
@@ -24313,8 +24564,8 @@ sap.ui.define([
24313
24564
  return that.oView.byId("table").getItems()[0].getBindingContext()
24314
24565
  .requestSideEffects([{$PropertyPath : "Country"}])
24315
24566
  .then(mustFail(assert), function (oError) {
24316
- assert.strictEqual(oError.message, "Must not request side effects for a context"
24317
- + " of a binding with $$aggregation");
24567
+ assert.strictEqual(oError.message,
24568
+ "Must not request side effects when using data aggregation");
24318
24569
  });
24319
24570
  });
24320
24571
  });
@@ -24467,7 +24718,7 @@ sap.ui.define([
24467
24718
  that.expectChange("count", "1");
24468
24719
 
24469
24720
  // code under test
24470
- that.oView.byId("count").setBindingContext(oListBinding.getHeaderContext());
24721
+ that.oView.byId("count").setBindingContext(oHeaderContext);
24471
24722
 
24472
24723
  return that.waitForChanges(assert, "$count");
24473
24724
  }).then(function () {
@@ -24569,11 +24820,6 @@ sap.ui.define([
24569
24820
  ]);
24570
24821
  assert.strictEqual(oListBinding.getCount(), 1, "count of nodes"); // code under test
24571
24822
 
24572
- assert.throws(function () {
24573
- // code under test (JIRA: CPOUI5ODATAV4-1851)
24574
- oListBinding.create();
24575
- }, new Error("Cannot create in " + oListBinding + " when using data aggregation"));
24576
-
24577
24823
  assert.throws(function () {
24578
24824
  // code under test (JIRA: CPOUI5ODATAV4-1851)
24579
24825
  oRoot.delete();
@@ -24753,7 +24999,7 @@ sap.ui.define([
24753
24999
  return Promise.all([
24754
25000
  // code under test
24755
25001
  // Note: $direct avoids "HTTP request was not processed because $batch failed"
24756
- oListBinding.getHeaderContext().requestSideEffects([""], "$direct")
25002
+ oHeaderContext.requestSideEffects([""], "$direct")
24757
25003
  .then(mustFail(assert), function (oError0) {
24758
25004
  assert.strictEqual(oError0, oError);
24759
25005
  }),
@@ -27228,6 +27474,175 @@ sap.ui.define([
27228
27474
  });
27229
27475
  });
27230
27476
 
27477
+ //*********************************************************************************************
27478
+ // Scenario: Show the single root node of a recursive hierarchy, which happens to be a leaf.
27479
+ // Create two new child nodes underneath.
27480
+ // Note: The "_Friend" navigation property is misused in order to have an artist play the role
27481
+ // of a hierarchy directory. This way, a draft root object is available (as needed by real
27482
+ // services).
27483
+ // JIRA: CPOUI5ODATAV4-1592
27484
+ QUnit.test("Recursive Hierarchy: create new children", function (assert) {
27485
+ var oChild, oListBinding, fnRespond, oRoot, oTable;
27486
+
27487
+ const oModel = this.createSpecialCasesModel({autoExpandSelect : true});
27488
+ const sFriend = "/Artists(ArtistID='99',IsActiveEntity=false)/_Friend";
27489
+ const sView = `
27490
+ <t:Table id="table" rows="{path : '/Artists(ArtistID=\\\'99\\\',IsActiveEntity=false)/_Friend',
27491
+ parameters : {
27492
+ $$aggregation : {
27493
+ hierarchyQualifier : 'OrgChart'
27494
+ }
27495
+ }}" threshold="0" visibleRowCount="3">
27496
+ <Text text="{= %{@$ui5.node.isExpanded} }"/>
27497
+ <Text text="{= %{@$ui5.node.level} }"/>
27498
+ <Text id="name" text="{Name}"/>
27499
+ </t:Table>`;
27500
+ const that = this;
27501
+
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
+ }, {
27510
+ "@odata.count" : "1",
27511
+ value : [{
27512
+ ArtistID : "0",
27513
+ IsActiveEntity : false,
27514
+ Name : "Alpha",
27515
+ _ : {
27516
+ // DescendantCount : "0", // not needed w/o expandTo
27517
+ // DistanceFromRoot : "0", // not needed w/o expandTo
27518
+ DrillState : "leaf",
27519
+ NodeID : "0,false"
27520
+ }
27521
+ }]
27522
+ })
27523
+ .expectChange("name", ["Alpha"]);
27524
+
27525
+ return this.createView(assert, sView, oModel).then(function () {
27526
+ oTable = that.oView.byId("table");
27527
+ oRoot = oTable.getRows()[0].getBindingContext();
27528
+ oListBinding = oRoot.getBinding();
27529
+
27530
+ checkTable("root is leaf", assert, oTable, [
27531
+ sFriend + "(ArtistID='0',IsActiveEntity=false)"
27532
+ ], [
27533
+ [undefined, 1, "Alpha"],
27534
+ ["", "", ""],
27535
+ ["", "", ""]
27536
+ ]);
27537
+ assert.strictEqual(oRoot.getIndex(), 0);
27538
+
27539
+ assert.throws(function () {
27540
+ // code under test (missing "@$ui5.node.parent")
27541
+ oListBinding.create({}, /*bSkipRefresh*/true);
27542
+ }); // TypeError: Cannot read properties of undefined (reading 'getCanonicalPath')
27543
+
27544
+ that.expectChange("name", [, "Beta"])
27545
+ .expectRequest({
27546
+ method : "POST",
27547
+ url : sFriend.slice(1),
27548
+ payload : {
27549
+ "BestFriend@odata.bind" : "Artists(ArtistID='0',IsActiveEntity=false)",
27550
+ Name : "Beta"
27551
+ }
27552
+ }, new Promise(function (resolve) {
27553
+ fnRespond = resolve.bind(null, {
27554
+ "@odata.etag" : "etag1.0",
27555
+ ArtistID : "1",
27556
+ IsActiveEntity : false,
27557
+ Name : "Beta: β" // side effect
27558
+ });
27559
+ }));
27560
+
27561
+ // code under test
27562
+ oChild = oListBinding.create({
27563
+ "@$ui5.node.parent" : oRoot,
27564
+ Name : "Beta"
27565
+ }, /*bSkipRefresh*/true);
27566
+
27567
+ return that.waitForChanges(assert, "create 1st child");
27568
+ }).then(function () {
27569
+ checkTable("during creation", assert, oTable, [
27570
+ sFriend + "(ArtistID='0',IsActiveEntity=false)",
27571
+ sFriend + "($uid=...)"
27572
+ ], [
27573
+ [true, 1, "Alpha"],
27574
+ [undefined, 2, "Beta"],
27575
+ ["", "", ""]
27576
+ ]);
27577
+ assert.strictEqual(oChild.getIndex(), 1);
27578
+
27579
+ that.expectChange("name", [, "Beta: β"]);
27580
+
27581
+ fnRespond();
27582
+
27583
+ return Promise.all([
27584
+ oChild.created(),
27585
+ that.waitForChanges(assert, "respond")
27586
+ ]);
27587
+ }).then(function () {
27588
+ checkTable("after creation", assert, oTable, [
27589
+ sFriend + "(ArtistID='0',IsActiveEntity=false)",
27590
+ sFriend + "(ArtistID='1',IsActiveEntity=false)"
27591
+ ], [
27592
+ [true, 1, "Alpha"],
27593
+ [undefined, 2, "Beta: β"],
27594
+ ["", "", ""]
27595
+ ]);
27596
+ assert.strictEqual(oChild.getIndex(), 1);
27597
+ assert.deepEqual(oChild.getObject(), {
27598
+ "@$ui5.context.isTransient" : false,
27599
+ "@$ui5.node.level" : 2,
27600
+ "@odata.etag" : "etag1.0",
27601
+ ArtistID : "1",
27602
+ IsActiveEntity : false,
27603
+ Name : "Beta: β"
27604
+ });
27605
+
27606
+ that.expectChange("name", [, "Gamma", "Beta: β"])
27607
+ .expectRequest({
27608
+ method : "POST",
27609
+ url : sFriend.slice(1),
27610
+ payload : {
27611
+ "BestFriend@odata.bind" : "Artists(ArtistID='0',IsActiveEntity=false)",
27612
+ Name : "Gamma"
27613
+ }
27614
+ }, {
27615
+ ArtistID : "2",
27616
+ IsActiveEntity : false,
27617
+ Name : "Gamma: γ" // side effect
27618
+ })
27619
+ .expectChange("name", [, "Gamma: γ"]);
27620
+
27621
+ // code under test
27622
+ oChild = oListBinding.create({
27623
+ "@$ui5.node.parent" : oRoot,
27624
+ Name : "Gamma"
27625
+ }, /*bSkipRefresh*/true);
27626
+
27627
+ assert.strictEqual(oChild.getIndex(), 1);
27628
+
27629
+ return Promise.all([
27630
+ oChild.created(),
27631
+ that.waitForChanges(assert, "create 2nd child")
27632
+ ]);
27633
+ }).then(function () {
27634
+ checkTable("after creation", assert, oTable, [
27635
+ sFriend + "(ArtistID='0',IsActiveEntity=false)",
27636
+ sFriend + "(ArtistID='2',IsActiveEntity=false)",
27637
+ sFriend + "(ArtistID='1',IsActiveEntity=false)"
27638
+ ], [
27639
+ [true, 1, "Alpha"],
27640
+ [undefined, 2, "Gamma: γ"],
27641
+ [undefined, 2, "Beta: β"]
27642
+ ]);
27643
+ });
27644
+ });
27645
+
27231
27646
  //*********************************************************************************************
27232
27647
  // Scenario: Application tries to overwrite client-side instance annotations.
27233
27648
  // JIRA: CPOUI5UISERVICESV3-1220
@@ -28503,8 +28918,7 @@ sap.ui.define([
28503
28918
  undefined, undefined, {$$updateGroupId : "doNotSubmit"}).create();
28504
28919
  oCreationRowContext.setProperty("Price", "47"); // BCP: 2270087626
28505
28920
 
28506
- that.expectChange("price", null) // timing issue, #setProperty is too slow :-(
28507
- .expectChange("price", "47")
28921
+ that.expectChange("price", "47")
28508
28922
  .expectChange("artistName", "The Beatles (modified)");
28509
28923
 
28510
28924
  oCreationRow.setBindingContext(oCreationRowContext);
@@ -28781,17 +29195,17 @@ sap.ui.define([
28781
29195
  .expectChange("currency");
28782
29196
 
28783
29197
  return this.createView(assert, sView, oModel).then(function () {
28784
- that.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)/_Publication"
28785
- + "?$select=Price,PublicationID&$skip=0&$top=5", {
28786
- value : []
28787
- })
28788
- .expectRequest("Artists(ArtistID='42',IsActiveEntity=true)"
29198
+ that.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)"
28789
29199
  + "?$select=ArtistID,IsActiveEntity,Name,defaultChannel", {
28790
29200
  ArtistID : "42",
28791
29201
  IsActiveEntity : true,
28792
29202
  Name : "Hour Frustrated",
28793
29203
  defaultChannel : "Channel 1"
28794
29204
  })
29205
+ .expectRequest("Artists(ArtistID='42',IsActiveEntity=true)/_Publication"
29206
+ + "?$select=Price,PublicationID&$skip=0&$top=5", {
29207
+ value : []
29208
+ })
28795
29209
  .expectChange("name", "Hour Frustrated");
28796
29210
 
28797
29211
  oObjectPage = that.oView.byId("objectPage");
@@ -28801,20 +29215,20 @@ sap.ui.define([
28801
29215
 
28802
29216
  return that.waitForChanges(assert);
28803
29217
  }).then(function () {
28804
- that.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)/_Publication"
28805
- + "?$select=Price,PublicationID&$skip=0&$top=5", {
28806
- value : [{
28807
- Price : "9.99",
28808
- PublicationID : "42-0"
28809
- }]
28810
- })
28811
- .expectRequest("Artists(ArtistID='42',IsActiveEntity=true)"
29218
+ that.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)"
28812
29219
  + "?$select=ArtistID,IsActiveEntity,Name,defaultChannel", {
28813
29220
  ArtistID : "42",
28814
29221
  IsActiveEntity : true,
28815
29222
  Name : "Hour Frustrated again",
28816
29223
  defaultChannel : "Channel 2"
28817
29224
  })
29225
+ .expectRequest("Artists(ArtistID='42',IsActiveEntity=true)/_Publication"
29226
+ + "?$select=Price,PublicationID&$skip=0&$top=5", {
29227
+ value : [{
29228
+ Price : "9.99",
29229
+ PublicationID : "42-0"
29230
+ }]
29231
+ })
28818
29232
  .expectChange("name", "Hour Frustrated again")
28819
29233
  .expectChange("price", ["9.99"])
28820
29234
  .expectChange("channel", ["Channel 2"]);
@@ -28835,20 +29249,20 @@ sap.ui.define([
28835
29249
 
28836
29250
  return that.waitForChanges(assert);
28837
29251
  }).then(function () {
28838
- that.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)/_Publication"
28839
- + "?$select=Price,PublicationID&$skip=0&$top=5", {
28840
- value : [{
28841
- Price : "10.99",
28842
- PublicationID : "42-0"
28843
- }]
28844
- })
28845
- .expectRequest("Artists(ArtistID='42',IsActiveEntity=true)"
29252
+ that.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)"
28846
29253
  + "?$select=ArtistID,IsActiveEntity,Name,defaultChannel", {
28847
29254
  ArtistID : "42",
28848
29255
  IsActiveEntity : true,
28849
29256
  Name : "Hour Frustrated again and again",
28850
29257
  defaultChannel : "Channel 3"
28851
29258
  })
29259
+ .expectRequest("Artists(ArtistID='42',IsActiveEntity=true)/_Publication"
29260
+ + "?$select=Price,PublicationID&$skip=0&$top=5", {
29261
+ value : [{
29262
+ Price : "10.99",
29263
+ PublicationID : "42-0"
29264
+ }]
29265
+ })
28852
29266
  .expectRequest("Artists(ArtistID='42',IsActiveEntity=true)/_Publication('42-0')"
28853
29267
  + "?$select=CurrencyCode", {CurrencyCode : "USD"})
28854
29268
  .expectChange("name", "Hour Frustrated again and again")
@@ -28871,10 +29285,17 @@ sap.ui.define([
28871
29285
  // entity via a bound action using another return value context.
28872
29286
  // The elements referenced via the navigation property must not be taken from the cache.
28873
29287
  // See CPOUI5UISERVICESV3-1686.
28874
- QUnit.test("return value contexts: don't reuse caches if context changed", function (assert) {
29288
+ //
29289
+ // Request an absolute side effect for the table below the R.V.C. (BCP: 2380046603)
29290
+ ["_Publication", "/special.cases.Container/Artists/_Publication"].forEach(function (sPath) {
29291
+ var sTitle = "return value contexts: don't reuse caches if context changed; side effect path: "
29292
+ + sPath;
29293
+
29294
+ QUnit.test(sTitle, function (assert) {
28875
29295
  var oActiveArtistContext,
28876
29296
  oInactiveArtistContext,
28877
29297
  oModel = this.createSpecialCasesModel({autoExpandSelect : true}),
29298
+ oNewActiveArtistContext,
28878
29299
  sView = '\
28879
29300
  <FlexBox id="objectPage">\
28880
29301
  <Text id="id" text="{ArtistID}"/>\
@@ -28920,7 +29341,7 @@ sap.ui.define([
28920
29341
  return that.waitForChanges(assert);
28921
29342
  }).then(function () {
28922
29343
  var oOperation = that.oModel.bindContext("special.cases.EditAction(...)",
28923
- that.oView.getBindingContext(), {$$inheritExpandSelect : true});
29344
+ oActiveArtistContext, {$$inheritExpandSelect : true});
28924
29345
 
28925
29346
  that.expectRequest({
28926
29347
  method : "POST",
@@ -28962,7 +29383,6 @@ sap.ui.define([
28962
29383
  url : "Artists(ArtistID='42',IsActiveEntity=false)/_Publication('42-0')",
28963
29384
  payload : {Price : "8.88"}
28964
29385
  }, {
28965
- "@odata.etag" : "ETag1",
28966
29386
  Price : "8.88"
28967
29387
  })
28968
29388
  .expectChange("price", ["8.88"]);
@@ -28988,7 +29408,7 @@ sap.ui.define([
28988
29408
  return that.waitForChanges(assert);
28989
29409
  }).then(function () {
28990
29410
  var oOperation = that.oModel.bindContext("special.cases.ActivationAction(...)",
28991
- that.oView.getBindingContext(), {$$inheritExpandSelect : true});
29411
+ oInactiveArtistContext, {$$inheritExpandSelect : true});
28992
29412
 
28993
29413
  that.expectRequest({
28994
29414
  method : "POST",
@@ -29007,7 +29427,7 @@ sap.ui.define([
29007
29427
  that.waitForChanges(assert)
29008
29428
  ]);
29009
29429
  }).then(function (aPromiseResults) {
29010
- var oNewActiveArtistContext = aPromiseResults[0];
29430
+ oNewActiveArtistContext = aPromiseResults[0];
29011
29431
 
29012
29432
  // new active artist context causes dependent binding to reload data
29013
29433
  that.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)/_Publication"
@@ -29023,8 +29443,37 @@ sap.ui.define([
29023
29443
  that.oView.setBindingContext(oNewActiveArtistContext);
29024
29444
 
29025
29445
  return that.waitForChanges(assert);
29446
+ }).then(function () {
29447
+ that.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)/_Publication"
29448
+ + "?$select=Price,PublicationID&$skip=0&$top=100", {
29449
+ value : [{
29450
+ Price : "8.89", // side effect
29451
+ PublicationID : "42-0"
29452
+ }]
29453
+ })
29454
+ .expectChange("price", ["8.89"]);
29455
+
29456
+ return Promise.all([
29457
+ oNewActiveArtistContext.requestSideEffects([sPath]),
29458
+ that.waitForChanges(assert, "side effect at R.V.C.")
29459
+ ]);
29460
+ }).then(function () {
29461
+ that.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)/_Publication"
29462
+ + "?$select=Price,PublicationID&$skip=0&$top=100", {
29463
+ value : [{
29464
+ Price : "8.99", // side effect
29465
+ PublicationID : "42-0"
29466
+ }]
29467
+ })
29468
+ .expectChange("price", ["8.99"]);
29469
+
29470
+ return Promise.all([
29471
+ oActiveArtistContext.requestSideEffects([sPath]),
29472
+ that.waitForChanges(assert, "side effect above operation binding")
29473
+ ]);
29026
29474
  });
29027
29475
  });
29476
+ });
29028
29477
 
29029
29478
  //*********************************************************************************************
29030
29479
  // Scenario: List and details containing a dependent table with an own request. Use
@@ -29157,7 +29606,7 @@ sap.ui.define([
29157
29606
  .expectChange("id", "42")
29158
29607
  .expectChange("isActive", "Yes")
29159
29608
  .expectChange("name", "Hour Frustrated")
29160
- .expectChange("inProcessByUser", null); // initialization due to #setContext
29609
+ .expectChange("inProcessByUser", ""); // initialization due to #setContext
29161
29610
 
29162
29611
  that.oView.setBindingContext(
29163
29612
  oModel.bindContext("/Artists(ArtistID='42',IsActiveEntity=true)", null,
@@ -29299,6 +29748,87 @@ sap.ui.define([
29299
29748
  });
29300
29749
  });
29301
29750
 
29751
+ //*********************************************************************************************
29752
+ // Scenario: An Edm.Stream property is requested as a "late" property and then inherited by an
29753
+ // "Edit" action which replaces the active version by a draft inside the (hidden) ODLB. The
29754
+ // property itself is missing from the response, but is not again requested.
29755
+ // BCP: 2380058514
29756
+ QUnit.test("BCP: 2380058514", function (assert) {
29757
+ var oContext,
29758
+ oModel = this.createSpecialCasesModel({autoExpandSelect : true}),
29759
+ sView = '\
29760
+ <FlexBox>\
29761
+ <Text id="id" text="{ArtistID}"/>\
29762
+ <Text id="isActive" text="{IsActiveEntity}"/>\
29763
+ <Text id="url" text="{Picture}"/>\
29764
+ </FlexBox>',
29765
+ that = this;
29766
+
29767
+ this.expectChange("id")
29768
+ .expectChange("isActive")
29769
+ .expectChange("url");
29770
+
29771
+ return this.createView(assert, sView, oModel).then(function () {
29772
+ that.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)"
29773
+ + "?$select=ArtistID,IsActiveEntity,Picture", {
29774
+ ArtistID : "42",
29775
+ IsActiveEntity : true
29776
+ // Picture property not seen here -> "Picture@$ui5.noData" : true
29777
+ // "Picture@odata.mediaContentType" etc. intentionally left out here
29778
+ })
29779
+ .expectChange("id", "42")
29780
+ .expectChange("isActive", "Yes")
29781
+ .expectChange("url",
29782
+ "/special/cases/Artists(ArtistID='42',IsActiveEntity=true)/Picture");
29783
+
29784
+ oContext = oModel.getKeepAliveContext("/Artists(ArtistID='42',IsActiveEntity=true)");
29785
+ that.oView.setBindingContext(oContext);
29786
+
29787
+ return that.waitForChanges(assert);
29788
+ }).then(function () {
29789
+ var oOperation = that.oModel.bindContext("special.cases.EditAction(...)", oContext,
29790
+ {$$inheritExpandSelect : true});
29791
+
29792
+ assert.deepEqual(oContext.getObject(), {
29793
+ ArtistID : "42",
29794
+ IsActiveEntity : true,
29795
+ "Picture@$ui5.noData" : true
29796
+ });
29797
+
29798
+ that.expectRequest({
29799
+ method : "POST",
29800
+ url : "Artists(ArtistID='42',IsActiveEntity=true)/special.cases.EditAction"
29801
+ + "?$select=ArtistID,IsActiveEntity,Picture",
29802
+ payload : {}
29803
+ }, {
29804
+ ArtistID : "42",
29805
+ IsActiveEntity : false
29806
+ // Picture property not seen here -> "Picture@$ui5.noData" : true
29807
+ // "Picture@odata.mediaContentType" etc. intentionally left out here
29808
+ });
29809
+
29810
+ return Promise.all([
29811
+ // code under test
29812
+ oOperation.execute(undefined, false, null, /*bReplaceWithRVC*/true),
29813
+ that.waitForChanges(assert)
29814
+ ]);
29815
+ }).then(function (aResults) {
29816
+ assert.deepEqual(aResults[0].getObject(), {
29817
+ ArtistID : "42",
29818
+ IsActiveEntity : false,
29819
+ "Picture@$ui5.noData" : true
29820
+ });
29821
+
29822
+ that.expectChange("isActive", "No")
29823
+ .expectChange("url",
29824
+ "/special/cases/Artists(ArtistID='42',IsActiveEntity=false)/Picture");
29825
+
29826
+ that.oView.setBindingContext(aResults[0]);
29827
+
29828
+ return that.waitForChanges(assert);
29829
+ });
29830
+ });
29831
+
29302
29832
  //*********************************************************************************************
29303
29833
  // Scenario: Call an action which returns the binding parameter as return value. Expect that
29304
29834
  // the result is copied back to the binding parameter.
@@ -31992,7 +32522,7 @@ sap.ui.define([
31992
32522
  SalesOrderID : "1",
31993
32523
  SO_2_BP : null
31994
32524
  })
31995
- .expectChange("company", null);
32525
+ .expectChange("company", "");
31996
32526
 
31997
32527
  return this.createView(assert, sView, oModel).then(function () {
31998
32528
  that.expectRequest("SalesOrderList('1')?$select=SO_2_BP"
@@ -32027,7 +32557,7 @@ sap.ui.define([
32027
32557
  + "&$expand=SO_2_BP($select=BusinessPartnerID,CompanyName)", {
32028
32558
  SO_2_BP : null
32029
32559
  })
32030
- .expectChange("company", null);
32560
+ .expectChange("company", "");
32031
32561
 
32032
32562
  return Promise.all([
32033
32563
  // code under test
@@ -32441,7 +32971,8 @@ sap.ui.define([
32441
32971
  }]
32442
32972
  })
32443
32973
  .expectChange("price", [,,,,,,, "7.77", "7.88"])
32444
- .expectChange("currency", [,,,,,,, "EUR", "EUR"]);
32974
+ .expectChange("currency", [,,,,,,, "EUR", "EUR"])
32975
+ .expectChange("inProcessByUser", [,,,,,,, "", ""]);
32445
32976
 
32446
32977
  oTable.setFirstVisibleRow(7);
32447
32978
 
@@ -35795,7 +36326,7 @@ sap.ui.define([
35795
36326
  // are formatted differently by sap.ui.model.odata.type.String#formatValue
35796
36327
  .expectChange("position", ["", "10"])
35797
36328
  .expectChange("quantity", [null, "7.000"])
35798
- .expectChange("product", [null, "2"])
36329
+ .expectChange("product", ["", "2"])
35799
36330
  .expectChange("position", ["20"])
35800
36331
  .expectChange("quantity", ["0.000"])
35801
36332
  .expectChange("product", ["3"])
@@ -37646,8 +38177,8 @@ sap.ui.define([
37646
38177
  BusinessPartnerId : "1",
37647
38178
  CompanyName : "SAP"
37648
38179
  })
37649
- .expectChange("city", [null])
37650
- .expectChange("type", [null])
38180
+ .expectChange("city", [""])
38181
+ .expectChange("type", [""])
37651
38182
  .expectChange("company", ["SAP"]);
37652
38183
 
37653
38184
  return Promise.all([
@@ -39298,7 +39829,7 @@ sap.ui.define([
39298
39829
  })
39299
39830
  .expectChange("budget", "1,234")
39300
39831
  .expectChange("name", "Team #1")
39301
- .expectChange("teamId", null);
39832
+ .expectChange("teamId", "");
39302
39833
 
39303
39834
  return this.createView(assert, sView, oModel).then(function () {
39304
39835
  oBinding = that.oView.byId("form").getObjectBinding();
@@ -39367,7 +39898,7 @@ sap.ui.define([
39367
39898
  TEAM_2_MANAGER : null
39368
39899
  })
39369
39900
  .expectChange("budget", "1,234")
39370
- .expectChange("teamId", null);
39901
+ .expectChange("teamId", "");
39371
39902
 
39372
39903
  oBinding.refresh();
39373
39904
 
@@ -43417,7 +43948,7 @@ sap.ui.define([
43417
43948
 
43418
43949
  return this.createView(assert, sView, oModel).then(function () {
43419
43950
  that.expectChange("name", ["John Doe"])
43420
- .expectChange("teamId", [null]);
43951
+ .expectChange("teamId", [""]);
43421
43952
 
43422
43953
  // code under test
43423
43954
  oContext = that.oView.byId("employees").getBinding("items")
@@ -44093,6 +44624,9 @@ sap.ui.define([
44093
44624
  // still unresolved. The object page must be useable nevertheless. In the end resolve the
44094
44625
  // list and see that it is in sync with the object page.
44095
44626
  // JIRA: CPOUI5ODATAV4-1407
44627
+ //
44628
+ // Reset the keep-alive status and request the active entity again in this scenario.
44629
+ // BCP: 441477 / 2023 (002075129400004414772023)
44096
44630
  // Steps:
44097
44631
  // (1) and (2) initialization in different order
44098
44632
  // (3) edit action
@@ -44409,6 +44943,10 @@ sap.ui.define([
44409
44943
  return that.waitForChanges(assert, "(6) cancel");
44410
44944
  }).then(function () {
44411
44945
  if (oFixture.list === 7) {
44946
+ oActiveContext.setKeepAlive(false);
44947
+ oActiveContext = that.oModel.getKeepAliveContext(
44948
+ "/Artists(ArtistID='A1',IsActiveEntity=true)", true,
44949
+ {$$patchWithoutSideEffects : true});
44412
44950
  initializeList(6);
44413
44951
  }
44414
44952
 
@@ -44846,6 +45384,259 @@ sap.ui.define([
44846
45384
  });
44847
45385
  });
44848
45386
 
45387
+ //*********************************************************************************************
45388
+ // Scenario: Flexible Column Layout, ODataModel#getKeepAliveContext
45389
+ // Object page requests a kept-alive context from an empty list. See that the object page
45390
+ // request's $select contains all properties from the list's $select even if there has not been
45391
+ // a late property yet.
45392
+ // Note that getKeepAliveContext requests the key properties (and poss. the messages). So in
45393
+ // order to have no late properties yet, the list must show all key properties, and messages
45394
+ // must not be requested. The test only has the shared property "Name" to avoid timing issues.
45395
+ // JIRA: CPOUI5ODATAV4-2190
45396
+ QUnit.test("getKeepAliveContext: properties from the list's $select", function (assert) {
45397
+ var oModel = this.createSpecialCasesModel({autoExpandSelect : true}),
45398
+ sView = '\
45399
+ <Table id="list" growing="true" growingThreshold="1" items="{path : \'Artists\',\
45400
+ parameters : {$$getKeepAliveContext : true, $$ownRequest : true}}">\
45401
+ <Text id="id" text="{ArtistID}"/>\
45402
+ <Text id="isActiveEntity" text="{IsActiveEntity}"/>\
45403
+ <Text id="listName" text="{Name}"/>\
45404
+ <Text id="listFriend" text="{BestFriend/Name}"/>\
45405
+ </Table>\
45406
+ <FlexBox id="objectPage">\
45407
+ <Text id="name" text="{Name}"/>\
45408
+ <Text id="friend" text="{BestFriend/Name}"/>\
45409
+ </FlexBox>',
45410
+ that = this;
45411
+
45412
+ this.expectChange("id", [])
45413
+ .expectChange("isActiveEntity", [])
45414
+ .expectChange("listName", [])
45415
+ .expectChange("listFriend", [])
45416
+ .expectChange("name")
45417
+ .expectChange("friend");
45418
+
45419
+ return this.createView(assert, sView, oModel).then(function () {
45420
+ that.expectRequest({
45421
+ batchNo : 1,
45422
+ url : "Artists?$select=ArtistID,IsActiveEntity,Name"
45423
+ + "&$expand=BestFriend($select=ArtistID,IsActiveEntity,Name)&$skip=0&$top=1"
45424
+ }, {
45425
+ value : [{
45426
+ ArtistID : "1",
45427
+ IsActiveEntity : true,
45428
+ Name : "The Who",
45429
+ BestFriend : {
45430
+ ArtistID : "2",
45431
+ IsActiveEntity : true,
45432
+ Name : "The The"
45433
+ }
45434
+ }]
45435
+ })
45436
+ .expectRequest({
45437
+ batchNo : 1,
45438
+ url : "Artists(ArtistID='3',IsActiveEntity=false)"
45439
+ + "?$select=ArtistID,IsActiveEntity,Name"
45440
+ + "&$expand=BestFriend($select=ArtistID,IsActiveEntity,Name)"
45441
+ }, {
45442
+ ArtistID : "3",
45443
+ IsActiveEntity : false,
45444
+ Name : "The Beatles",
45445
+ BestFriend : {
45446
+ ArtistID : "4",
45447
+ IsActiveEntity : true,
45448
+ Name : "The Rolling Stones"
45449
+ }
45450
+ })
45451
+ .expectChange("id", ["1"])
45452
+ .expectChange("isActiveEntity", ["Yes"])
45453
+ .expectChange("listName", ["The Who"])
45454
+ .expectChange("listFriend", ["The The"])
45455
+ .expectChange("name", "The Beatles")
45456
+ .expectChange("friend", "The Rolling Stones");
45457
+
45458
+ that.oView.byId("list").setBindingContext(oModel.createBindingContext("/"));
45459
+ that.oView.byId("objectPage").setBindingContext(
45460
+ oModel.getKeepAliveContext("/Artists(ArtistID='3',IsActiveEntity=false)"));
45461
+
45462
+ return that.waitForChanges(assert);
45463
+ });
45464
+ });
45465
+
45466
+ //*********************************************************************************************
45467
+ // Scenario: Flexible Column Layout, ODataModel#getKeepAliveContext
45468
+ // Object page requests a kept-alive context. The context's keep-alive status is removed, either
45469
+ // still in the temporary binding or hidden in the $$getKeepAliveContext binding. Later a
45470
+ // kept-alive context for the same path is requested; its data must be read from the server
45471
+ // again.
45472
+ // BCP: 441477 / 2023 (002075129400004414772023)
45473
+ [false, true].forEach(function (bTemporary) {
45474
+ var sTitle = "BCP: 441477 / 2023: getKeepAliveContext, temporary=" + bTemporary;
45475
+
45476
+ QUnit.test(sTitle, function (assert) {
45477
+ var oContext,
45478
+ oListBinding,
45479
+ oModel = this.createSpecialCasesModel({autoExpandSelect : true}),
45480
+ oObjectPage,
45481
+ sView = '\
45482
+ <Table id="list" growing="true" growingThreshold="1"\
45483
+ items="{path : \'/Artists\', parameters : {$$getKeepAliveContext : true},\
45484
+ suspended : true}">\
45485
+ <Text id="listName" text="{Name}"/>\
45486
+ </Table>\
45487
+ <FlexBox id="objectPage">\
45488
+ <Text id="name" text="{Name}"/>\
45489
+ </FlexBox>',
45490
+ that = this;
45491
+
45492
+ this.expectChange("listName", [])
45493
+ .expectChange("name");
45494
+
45495
+ return this.createView(assert, sView, oModel).then(function () {
45496
+ that.expectRequest("Artists(ArtistID='3',IsActiveEntity=false)"
45497
+ + "?$select=ArtistID,IsActiveEntity,Name", {
45498
+ ArtistID : "3",
45499
+ IsActiveEntity : false,
45500
+ Name : "The Beatles"
45501
+ })
45502
+ .expectChange("name", "The Beatles");
45503
+
45504
+ oContext = oModel.getKeepAliveContext("/Artists(ArtistID='3',IsActiveEntity=false)");
45505
+ oObjectPage = that.oView.byId("objectPage");
45506
+ oObjectPage.setBindingContext(oContext);
45507
+
45508
+ return that.waitForChanges(assert, "1st getKeepAliveContext");
45509
+ }).then(function () {
45510
+ if (!bTemporary) {
45511
+ that.expectRequest("Artists?$select=ArtistID,IsActiveEntity,Name"
45512
+ + "&$skip=0&$top=1", {
45513
+ value : [{
45514
+ ArtistID : "1",
45515
+ IsActiveEntity : true,
45516
+ Name : "The Who"
45517
+ }]
45518
+ })
45519
+ .expectChange("listName", ["The Who"]);
45520
+
45521
+ oListBinding = that.oView.byId("list").getBinding("items");
45522
+ oListBinding.resume();
45523
+
45524
+ return that.waitForChanges(assert, "transfer to the list");
45525
+ }
45526
+ }).then(function () {
45527
+ if (!bTemporary) {
45528
+ assert.strictEqual(oContext.getBinding(), oListBinding, "transferred to the list");
45529
+ }
45530
+
45531
+ that.expectChange("name", null);
45532
+
45533
+ oObjectPage.setBindingContext(null); // unbind before destruction
45534
+
45535
+ // code under test
45536
+ oContext.setKeepAlive(false);
45537
+
45538
+ return that.waitForChanges(assert, "setKeepAlive(false)");
45539
+ }).then(function () {
45540
+ that.expectRequest("Artists(ArtistID='3',IsActiveEntity=false)"
45541
+ + "?$select=ArtistID,IsActiveEntity,Name", {
45542
+ ArtistID : "3",
45543
+ IsActiveEntity : false,
45544
+ Name : "The Beatles *"
45545
+ })
45546
+ .expectChange("name", "The Beatles *");
45547
+
45548
+ oContext = oModel.getKeepAliveContext("/Artists(ArtistID='3',IsActiveEntity=false)");
45549
+ oObjectPage.setBindingContext(oContext);
45550
+
45551
+ return that.waitForChanges(assert, "2nd getKeepAliveContext");
45552
+ });
45553
+ });
45554
+ });
45555
+
45556
+ //*********************************************************************************************
45557
+ // Scenario: Flexible Column Layout, ODataModel#getKeepAliveContext
45558
+ // Object page requests a hidden kept-alive context for a list with data. The context's
45559
+ // keep-alive status is removed. Later the entity is changed on the server and then loaded via
45560
+ // paging, it must show the new data.
45561
+ // BCP: 441477 / 2023 (002075129400004414772023)
45562
+ [false, true].forEach(function (bETag) {
45563
+ var sTitle = "BCP: 441477 / 2023: getKeepAliveContext & paging, eTag=" + bETag;
45564
+
45565
+ QUnit.test(sTitle, function (assert) {
45566
+ var oContext,
45567
+ oModel = this.createSpecialCasesModel({autoExpandSelect : true}),
45568
+ oObjectPage,
45569
+ sView = '\
45570
+ <Table id="list" growing="true" growingThreshold="1" \
45571
+ items="{path : \'/Artists\', parameters : {$$getKeepAliveContext : true}}">\
45572
+ <Text id="listName" text="{Name}"/>\
45573
+ </Table>\
45574
+ <FlexBox id="objectPage">\
45575
+ <Text id="name" text="{Name}"/>\
45576
+ </FlexBox>',
45577
+ that = this;
45578
+
45579
+ this.expectRequest("Artists?$select=ArtistID,IsActiveEntity,Name"
45580
+ + "&$skip=0&$top=1", {
45581
+ value : [{
45582
+ ArtistID : "1",
45583
+ IsActiveEntity : true,
45584
+ Name : "The Who"
45585
+ }]
45586
+ })
45587
+ .expectChange("listName", ["The Who"])
45588
+ .expectChange("name");
45589
+
45590
+ return this.createView(assert, sView, oModel).then(function () {
45591
+ var oResponse = {
45592
+ ArtistID : "3",
45593
+ IsActiveEntity : false,
45594
+ Name : "The Beatles"
45595
+ };
45596
+
45597
+ if (bETag) {
45598
+ oResponse["@odata.etag"] = "etag1";
45599
+ }
45600
+ that.expectRequest("Artists(ArtistID='3',IsActiveEntity=false)"
45601
+ + "?$select=ArtistID,IsActiveEntity,Name",
45602
+ oResponse)
45603
+ .expectChange("name", "The Beatles");
45604
+
45605
+ oContext = oModel.getKeepAliveContext("/Artists(ArtistID='3',IsActiveEntity=false)");
45606
+ oObjectPage = that.oView.byId("objectPage");
45607
+ oObjectPage.setBindingContext(oContext);
45608
+
45609
+ return that.waitForChanges(assert, "getKeepAliveContext");
45610
+ }).then(function () {
45611
+ that.expectChange("name", null);
45612
+
45613
+ oObjectPage.setBindingContext(null); // unbind before destruction
45614
+
45615
+ // code under test
45616
+ oContext.setKeepAlive(false);
45617
+
45618
+ return that.waitForChanges(assert, "setKeepAlive(false)");
45619
+ }).then(function () {
45620
+ var oResponse = {
45621
+ ArtistID : "3",
45622
+ IsActiveEntity : false,
45623
+ Name : "The Beatles *"
45624
+ };
45625
+
45626
+ if (bETag) {
45627
+ oResponse["@odata.etag"] = "etag2";
45628
+ }
45629
+ that.expectRequest("Artists?$select=ArtistID,IsActiveEntity,Name&$skip=1&$top=1",
45630
+ {value : [oResponse]})
45631
+ .expectChange("listName", [, "The Beatles *"]);
45632
+
45633
+ that.oView.byId("list").requestItems();
45634
+
45635
+ return that.waitForChanges(assert, "request more items");
45636
+ });
45637
+ });
45638
+ });
45639
+
44849
45640
  //*********************************************************************************************
44850
45641
  // Scenario: List report with absolute binding, object page with a late property. Ensure that
44851
45642
  // the late property is not requested for all rows of the list, but only for the single row that
@@ -48968,6 +49759,8 @@ sap.ui.define([
48968
49759
  // The response has fewer nested entities in different order (CPOUI5ODATAV4-2079)
48969
49760
  // Nested entities via initial data and via #create (CPOUI5ODATAV4-2036)
48970
49761
  // Optimize the refresh after create w/o bSkipRefresh (CPOUI5ODATAV4-2048)
49762
+ // Accept the complete response, not only $select (esp. GrossAmount) (CPOUI5ODATAV4-1977)
49763
+ // Also create the product (nested single below collection) (CPOUI5ODATAV4-1977)
48971
49764
  [false, true].forEach(function (bSkipRefresh) {
48972
49765
  var sTitle = "CPOUI5ODATAV4-1973: Deep create, nested ODLB w/o cache, bSkipRefresh="
48973
49766
  + bSkipRefresh;
@@ -48983,26 +49776,33 @@ sap.ui.define([
48983
49776
  <Text id="order" text="{SalesOrderID}"/>\
48984
49777
  <Table items="{path : \'SO_2_SOITEM\', templateShareable : true}">\
48985
49778
  <Input id="note" value="{Note}"/>\
49779
+ <Text id="productId" text="{SOITEM_2_PRODUCT/ProductID}"/>\
49780
+ <Input id="productName" value="{SOITEM_2_PRODUCT/Name}"/>\
48986
49781
  </Table>\
48987
49782
  </Table>',
48988
49783
  that = this;
48989
49784
 
48990
49785
  this.expectRequest("SalesOrderList?$select=SalesOrderID"
48991
- + "&$expand=SO_2_SOITEM($select=ItemPosition,Note,SalesOrderID)&$skip=0&$top=100",
49786
+ + "&$expand=SO_2_SOITEM($select=ItemPosition,Note,SalesOrderID"
49787
+ + ";$expand=SOITEM_2_PRODUCT($select=Name,ProductID))&$skip=0&$top=100",
48992
49788
  {value : []})
48993
49789
  .expectChange("order", [])
48994
- .expectChange("note", []);
49790
+ .expectChange("note", [])
49791
+ .expectChange("productId", [])
49792
+ .expectChange("productName", []);
48995
49793
 
48996
49794
  return this.createView(assert, sView, oModel).then(function () {
48997
49795
  that.expectChange("order", [""])
48998
- .expectChange("note", ["A", "B"]);
49796
+ .expectChange("note", ["A", "B"])
49797
+ .expectChange("productId", ["", ""])
49798
+ .expectChange("productName", ["PA", ""]);
48999
49799
 
49000
49800
  oOrdersBinding = that.oView.byId("orders").getBinding("items");
49001
49801
 
49002
49802
  // code under test
49003
49803
  oCreatedOrderContext = oOrdersBinding.create({
49004
49804
  SO_2_SOITEM : [
49005
- {Note : "A"},
49805
+ {Note : "A", SOITEM_2_PRODUCT : {Name : "PA"}},
49006
49806
  {Note : "B"}
49007
49807
  ]
49008
49808
  }, bSkipRefresh);
@@ -49016,7 +49816,10 @@ sap.ui.define([
49016
49816
  aContexts = oItemsBinding.getCurrentContexts();
49017
49817
  assert.deepEqual(aContexts.map(getObject), [{
49018
49818
  "@$ui5.context.isTransient" : true,
49019
- Note : "A"
49819
+ Note : "A",
49820
+ SOITEM_2_PRODUCT : {
49821
+ Name : "PA"
49822
+ }
49020
49823
  }, {
49021
49824
  "@$ui5.context.isTransient" : true,
49022
49825
  Note : "B"
@@ -49025,19 +49828,28 @@ sap.ui.define([
49025
49828
  assert.strictEqual(oContext.isTransient(), true);
49026
49829
  });
49027
49830
 
49028
- that.expectChange("note", [,, "C", "D"]);
49831
+ that.expectChange("note", [,, "C", "D"])
49832
+ .expectChange("productId", [,, "", ""])
49833
+ .expectChange("productName", [, "PB", "", ""]);
49029
49834
 
49030
49835
  // code under test
49836
+ aContexts[1].setProperty("SOITEM_2_PRODUCT/Name", "PB");
49031
49837
  oItemsBinding.create({Note : "C"}, false, true); // at end
49032
49838
  oItemsBinding.create({Note : "D"}, false, true); // at end
49033
49839
 
49034
49840
  aContexts = oItemsBinding.getCurrentContexts();
49035
49841
  assert.deepEqual(aContexts.map(getObject), [{
49036
49842
  "@$ui5.context.isTransient" : true,
49037
- Note : "A"
49843
+ Note : "A",
49844
+ SOITEM_2_PRODUCT : {
49845
+ Name : "PA"
49846
+ }
49038
49847
  }, {
49039
49848
  "@$ui5.context.isTransient" : true,
49040
- Note : "B"
49849
+ Note : "B",
49850
+ SOITEM_2_PRODUCT : {
49851
+ Name : "PB"
49852
+ }
49041
49853
  }, {
49042
49854
  "@$ui5.context.isTransient" : true,
49043
49855
  Note : "C"
@@ -49077,38 +49889,52 @@ sap.ui.define([
49077
49889
  url : "SalesOrderList",
49078
49890
  payload : {
49079
49891
  SO_2_SOITEM : [
49080
- {Note : "AA"},
49081
- {Note : "BB"},
49892
+ {Note : "AA", SOITEM_2_PRODUCT : {Name : "PA"}},
49893
+ {Note : "BB", SOITEM_2_PRODUCT : {Name : "PB"}},
49082
49894
  {Note : "CC"},
49083
49895
  {Note : "DD"}
49084
49896
  ]
49085
49897
  }
49086
49898
  }, {
49087
49899
  "@odata.etag" : "etag",
49900
+ GrossAmount : "128.97",
49088
49901
  SalesOrderID : "new",
49089
49902
  SO_2_SOITEM : [{
49090
49903
  "@odata.etag" : "etag10",
49091
- GrossAmount : "42.99", // excess property
49904
+ GrossAmount : "41.99",
49092
49905
  ItemPosition : "0010",
49093
49906
  Note : "AAA",
49094
- SalesOrderID : "new"
49907
+ SalesOrderID : "new",
49908
+ SOITEM_2_PRODUCT : {
49909
+ "@odata.etag" : "etagP1",
49910
+ Name : "PA",
49911
+ ProductID : "P1"
49912
+ }
49095
49913
  }, {
49096
49914
  "@odata.etag" : "etag20",
49097
- GrossAmount : "42.99", // excess property
49915
+ GrossAmount : "42.99",
49098
49916
  ItemPosition : "0020",
49099
49917
  Note : "CCC",
49100
- SalesOrderID : "new"
49918
+ SalesOrderID : "new",
49919
+ SOITEM_2_PRODUCT : null
49101
49920
  }, {
49102
49921
  "@odata.etag" : "etag30",
49103
- GrossAmount : "42.99", // excess property
49922
+ GrossAmount : "43.99",
49104
49923
  ItemPosition : "0030",
49105
49924
  Note : "BBB",
49106
- SalesOrderID : "new"
49925
+ SalesOrderID : "new",
49926
+ SOITEM_2_PRODUCT : {
49927
+ "@odata.etag" : "etagP2",
49928
+ Name : "PB",
49929
+ ProductID : "P2"
49930
+ }
49107
49931
  }]
49108
49932
  })
49109
49933
  // optimized refresh: even w/o bSkipRefresh nothing is requested
49110
49934
  .expectChange("order", ["new"])
49111
- .expectChange("note", ["AAA", "CCC", "BBB"]);
49935
+ .expectChange("note", ["AAA", "CCC", "BBB"])
49936
+ .expectChange("productId", ["P1", , "P2"])
49937
+ .expectChange("productName", [, "", "PB"]);
49112
49938
 
49113
49939
  that.expectCanceledError(
49114
49940
  "Deep create of SalesOrderList succeeded. Do not use this promise.")
@@ -49128,8 +49954,8 @@ sap.ui.define([
49128
49954
  that.waitForChanges(assert, "submit POST")
49129
49955
  ].flat());
49130
49956
  }).then(function () {
49131
- var aContexts = oItemsBinding.getAllCurrentContexts();
49132
-
49957
+ assert.strictEqual(oCreatedOrderContext.getProperty("GrossAmount"), "128.97");
49958
+ const aContexts = oItemsBinding.getAllCurrentContexts();
49133
49959
  assert.deepEqual(aContexts.map(getPath), [
49134
49960
  "/SalesOrderList('new')/SO_2_SOITEM(SalesOrderID='new',ItemPosition='0010')",
49135
49961
  "/SalesOrderList('new')/SO_2_SOITEM(SalesOrderID='new',ItemPosition='0020')",
@@ -49137,19 +49963,33 @@ sap.ui.define([
49137
49963
  ]);
49138
49964
  assert.deepEqual(aContexts.map(getObject), [{
49139
49965
  "@odata.etag" : "etag10",
49966
+ GrossAmount : "41.99",
49140
49967
  ItemPosition : "0010",
49141
49968
  Note : "AAA",
49142
- SalesOrderID : "new"
49969
+ SalesOrderID : "new",
49970
+ SOITEM_2_PRODUCT : {
49971
+ "@odata.etag" : "etagP1",
49972
+ Name : "PA",
49973
+ ProductID : "P1"
49974
+ }
49143
49975
  }, {
49144
49976
  "@odata.etag" : "etag20",
49977
+ GrossAmount : "42.99",
49145
49978
  ItemPosition : "0020",
49146
49979
  Note : "CCC",
49147
- SalesOrderID : "new"
49980
+ SalesOrderID : "new",
49981
+ SOITEM_2_PRODUCT : null
49148
49982
  }, {
49149
49983
  "@odata.etag" : "etag30",
49984
+ GrossAmount : "43.99",
49150
49985
  ItemPosition : "0030",
49151
49986
  Note : "BBB",
49152
- SalesOrderID : "new"
49987
+ SalesOrderID : "new",
49988
+ SOITEM_2_PRODUCT : {
49989
+ "@odata.etag" : "etagP2",
49990
+ Name : "PB",
49991
+ ProductID : "P2"
49992
+ }
49153
49993
  }]);
49154
49994
 
49155
49995
  that.expectChange("note", ["AAAA"])
@@ -49189,6 +50029,8 @@ sap.ui.define([
49189
50029
  // response, and the item a $expand to the Product. Also check that the
49190
50030
  // @$ui5.context.isTransient annotation fires all change events.
49191
50031
  // CPOUI5ODATAV4-2048
50032
+ //
50033
+ // Accept the complete response, not only $select (esp. GrossAmount) (CPOUI5ODATAV4-1977)
49192
50034
  [false, true].forEach(function (bSkipRefresh) {
49193
50035
  var sTitle = "CPOUI5ODATAV4-2033: Deep create, nested ODLB w/ own cache, bSkipRefresh="
49194
50036
  + bSkipRefresh;
@@ -49236,7 +50078,7 @@ sap.ui.define([
49236
50078
  return this.createView(assert, sView, oModel).then(function () {
49237
50079
  that.expectChange("isTransient", [true, undefined])
49238
50080
  .expectChange("order", ["", "1"])
49239
- .expectChange("bp", null)
50081
+ .expectChange("bp", "")
49240
50082
  .expectChange("currency", "EUR") // default value
49241
50083
  .expectChange("orderCount", "2")
49242
50084
  .expectChange("itemCount", "0");
@@ -49254,7 +50096,7 @@ sap.ui.define([
49254
50096
  return that.waitForChanges(assert, "create order");
49255
50097
  }).then(function () {
49256
50098
  that.expectChange("note", ["AA", "doNotSubmit", "B"])
49257
- .expectChange("product", [null, null, null])
50099
+ .expectChange("product", ["", "", ""])
49258
50100
  .expectChange("itemCount", "1")
49259
50101
  .expectChange("itemCount", "2")
49260
50102
  .expectChange("itemCount", "3");
@@ -49327,22 +50169,23 @@ sap.ui.define([
49327
50169
  }
49328
50170
  }, {
49329
50171
  "@odata.etag" : "etag",
50172
+ GrossAmount : "128.97",
49330
50173
  SalesOrderID : "new",
49331
50174
  SO_2_SOITEM : [{
49332
50175
  "@odata.etag" : "etag10",
49333
- GrossAmount : "42.99", // excess property
50176
+ GrossAmount : "41.99",
49334
50177
  ItemPosition : "0010",
49335
50178
  Note : "BBB",
49336
50179
  SalesOrderID : "new"
49337
50180
  }, {
49338
50181
  "@odata.etag" : "etag20",
49339
- GrossAmount : "42.99", // excess property
50182
+ GrossAmount : "42.99",
49340
50183
  ItemPosition : "0020",
49341
50184
  Note : "additional",
49342
50185
  SalesOrderID : "new"
49343
50186
  }, {
49344
50187
  "@odata.etag" : "etag30",
49345
- GrossAmount : "42.99", // excess property
50188
+ GrossAmount : "43.99",
49346
50189
  ItemPosition : "0030",
49347
50190
  Note : "AAA",
49348
50191
  SalesOrderID : "new"
@@ -49460,8 +50303,8 @@ sap.ui.define([
49460
50303
  that.waitForChanges(assert, "submit -> success")
49461
50304
  ]);
49462
50305
  }).then(function () {
49463
- var aContexts = oItemsBinding.getAllCurrentContexts();
49464
-
50306
+ assert.strictEqual(oCreatedOrderContext.getProperty("GrossAmount"), "128.97");
50307
+ const aContexts = oItemsBinding.getAllCurrentContexts();
49465
50308
  assert.strictEqual(oCreatedOrderContext.getValue("@$ui5.context.isTransient"), false);
49466
50309
  assert.strictEqual(oCreatedOrderContext.getValue("SO_2_BP/BusinessPartnerID"), "BP");
49467
50310
  assert.deepEqual(aContexts.map(getPath), [
@@ -49472,6 +50315,7 @@ sap.ui.define([
49472
50315
  assert.deepEqual(aContexts.map(getObject), [{
49473
50316
  "@odata.etag" : "etag10",
49474
50317
  ItemPosition : "0010",
50318
+ GrossAmount : "41.99",
49475
50319
  Note : "BBB",
49476
50320
  SalesOrderID : "new",
49477
50321
  SOITEM_2_PRODUCT : {
@@ -49482,6 +50326,7 @@ sap.ui.define([
49482
50326
  }, {
49483
50327
  "@odata.etag" : "etag20",
49484
50328
  ItemPosition : "0020",
50329
+ GrossAmount : "42.99",
49485
50330
  Note : "additional",
49486
50331
  SalesOrderID : "new",
49487
50332
  SOITEM_2_PRODUCT : {
@@ -49492,6 +50337,7 @@ sap.ui.define([
49492
50337
  }, {
49493
50338
  "@odata.etag" : "etag30",
49494
50339
  ItemPosition : "0030",
50340
+ GrossAmount : "43.99",
49495
50341
  Note : "AAA",
49496
50342
  SalesOrderID : "new",
49497
50343
  SOITEM_2_PRODUCT : {
@@ -49680,6 +50526,8 @@ sap.ui.define([
49680
50526
  // (5) Delete the second employee
49681
50527
  // (6) Submit; the number of equipment items changes for each employee
49682
50528
  // JIRA: CPOUI5ODATAV4-1976
50529
+ //
50530
+ // Accept the complete response, not only $select (esp. EmployeeId) (CPOUI5ODATAV4-1977)
49683
50531
  [false, true].forEach(function (bOwnRequest) {
49684
50532
  ["Table", "t:Table"].forEach(function (sTable) {
49685
50533
  var sTitle = "CPOUI5ODATAV4-1976: Deep create, nested list in nested list, $$ownRequest="
@@ -49846,11 +50694,13 @@ sap.ui.define([
49846
50694
  EMPLOYEE_2_EQUIPMENTS : [{
49847
50695
  "@odata.etag" : "etag.P1",
49848
50696
  Category : "C",
50697
+ EmployeeId : "E1",
49849
50698
  ID : 1,
49850
50699
  Name : "P1"
49851
50700
  }, {
49852
50701
  "@odata.etag" : "etag.P2",
49853
50702
  Category : "C",
50703
+ EmployeeId : "E1",
49854
50704
  ID : 2,
49855
50705
  Name : "P2"
49856
50706
  }]
@@ -49861,6 +50711,7 @@ sap.ui.define([
49861
50711
  EMPLOYEE_2_EQUIPMENTS : [{
49862
50712
  "@odata.etag" : "etag.F1",
49863
50713
  Category : "C",
50714
+ EmployeeId : "E2",
49864
50715
  ID : 3,
49865
50716
  Name : "F1"
49866
50717
  }]
@@ -49898,17 +50749,20 @@ sap.ui.define([
49898
50749
  assert.deepEqual(aEquipmentsBindings[0].getAllCurrentContexts().map(getObject), [{
49899
50750
  "@odata.etag" : "etag.P1",
49900
50751
  Category : "C",
50752
+ EmployeeId : "E1",
49901
50753
  ID : 1,
49902
50754
  Name : "P1"
49903
50755
  }, {
49904
50756
  "@odata.etag" : "etag.P2",
49905
50757
  Category : "C",
50758
+ EmployeeId : "E1",
49906
50759
  ID : 2,
49907
50760
  Name : "P2"
49908
50761
  }]);
49909
50762
  assert.deepEqual(aEquipmentsBindings[1].getAllCurrentContexts().map(getObject), [{
49910
50763
  "@odata.etag" : "etag.F1",
49911
50764
  Category : "C",
50765
+ EmployeeId : "E2",
49912
50766
  ID : 3,
49913
50767
  Name : "F1"
49914
50768
  }]);
@@ -49917,6 +50771,127 @@ sap.ui.define([
49917
50771
  });
49918
50772
  });
49919
50773
 
50774
+ //*********************************************************************************************
50775
+ // Scenario: Deep create, nested single entity incl. recursion.
50776
+ // Create an employee with a nested team (one property via initial data, another one set
50777
+ // afterward) with a nested manager. See that the complete response is accepted, not only
50778
+ // $select (esp. Name, MEMBER_COUNT)
50779
+ // JIRA: CPOUI5ODATAV4-1977
50780
+ QUnit.test("CPOUI5ODATAV4-1977: Deep create, nested single entity", function (assert) {
50781
+ let oBinding;
50782
+ let oCreatedContext;
50783
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true, updateGroupId : "update"});
50784
+ const sView = `
50785
+ <Table id="employees" items="{/EMPLOYEES}">
50786
+ <Text id="id" text="{ID}"/>
50787
+ <Text id="teamId" text="{EMPLOYEE_2_TEAM/Team_Id}"/>
50788
+ <Input id="teamName" value="{EMPLOYEE_2_TEAM/Name}"/>
50789
+ <Input id="manager" value="{EMPLOYEE_2_TEAM/TEAM_2_MANAGER/ID}"/>
50790
+ <Text id="managerTeamId" text="{EMPLOYEE_2_TEAM/TEAM_2_MANAGER/TEAM_ID}"/>
50791
+ </Table>`;
50792
+ const that = this;
50793
+
50794
+ this.expectRequest("EMPLOYEES?$select=ID&$expand=EMPLOYEE_2_TEAM($select=Name,Team_Id"
50795
+ + ";$expand=TEAM_2_MANAGER($select=ID,TEAM_ID))&$skip=0&$top=100", {
50796
+ value : [{
50797
+ ID : "E1",
50798
+ EMPLOYEE_2_TEAM : {
50799
+ Name : "Team 1",
50800
+ Team_Id : "T1",
50801
+ TEAM_2_MANAGER : {
50802
+ ID : "M1",
50803
+ TEAM_ID : "T1"
50804
+ }
50805
+ }
50806
+ }]
50807
+ })
50808
+ .expectChange("id", ["E1"])
50809
+ .expectChange("teamId", ["T1"])
50810
+ .expectChange("teamName", ["Team 1"])
50811
+ .expectChange("manager", ["M1"])
50812
+ .expectChange("managerTeamId", ["T1"]);
50813
+
50814
+ return this.createView(assert, sView, oModel).then(function () {
50815
+ that.expectChange("id", ["", "E1"])
50816
+ .expectChange("teamId", ["Tnew", "T1"])
50817
+ .expectChange("teamName", ["", "Team 1"])
50818
+ .expectChange("manager", ["", "M1"])
50819
+ .expectChange("managerTeamId", ["", "T1"]);
50820
+
50821
+ oBinding = that.oView.byId("employees").getBinding("items");
50822
+ // code under test
50823
+ // bSkipRefresh not needed due to deep create
50824
+ oCreatedContext = oBinding.create({EMPLOYEE_2_TEAM : {Team_Id : "Tnew"}});
50825
+
50826
+ return that.waitForChanges(assert, "create employee");
50827
+ }).then(function () {
50828
+ that.expectChange("teamName", ["Team 2"])
50829
+ .expectChange("manager", ["M2"]);
50830
+
50831
+ oCreatedContext.setProperty("EMPLOYEE_2_TEAM/Name", "Team 2");
50832
+ oCreatedContext.setProperty("EMPLOYEE_2_TEAM/TEAM_2_MANAGER/ID", "M2");
50833
+
50834
+ return that.waitForChanges(assert, "patch transient");
50835
+ }).then(function () {
50836
+ that.expectRequest({
50837
+ method : "POST",
50838
+ url : "EMPLOYEES",
50839
+ payload : {
50840
+ EMPLOYEE_2_TEAM : {
50841
+ Name : "Team 2",
50842
+ Team_Id : "Tnew",
50843
+ TEAM_2_MANAGER : {
50844
+ ID : "M2"
50845
+ }
50846
+ }
50847
+ }
50848
+ }, {
50849
+ "@odata.etag" : "etagE2",
50850
+ ID : "E2",
50851
+ Name : "Peter Burke",
50852
+ EMPLOYEE_2_TEAM : {
50853
+ "@odata.etag" : "etagT2",
50854
+ MEMBER_COUNT : 1,
50855
+ Name : "Team 2 (from server)",
50856
+ Team_Id : "T2",
50857
+ TEAM_2_MANAGER : {
50858
+ "@odata.etag" : "etagM2",
50859
+ ID : "M2",
50860
+ TEAM_ID : "T2"
50861
+ }
50862
+ }
50863
+ })
50864
+ .expectChange("id", ["E2"])
50865
+ .expectChange("teamId", ["T2"])
50866
+ .expectChange("teamName", ["Team 2 (from server)"])
50867
+ .expectChange("managerTeamId", ["T2"]);
50868
+
50869
+ return Promise.all([
50870
+ oModel.submitBatch("update"),
50871
+ oCreatedContext.created(),
50872
+ that.waitForChanges(assert, "submit")
50873
+ ]);
50874
+ }).then(function () {
50875
+ assert.deepEqual(oCreatedContext.getObject(), {
50876
+ "@$ui5.context.isTransient" : false,
50877
+ "@odata.etag" : "etagE2",
50878
+ ID : "E2",
50879
+ Name : "Peter Burke",
50880
+ EMPLOYEE_2_TEAM : {
50881
+ "@odata.etag" : "etagT2",
50882
+ MEMBER_COUNT : 1,
50883
+ Name : "Team 2 (from server)",
50884
+ Team_Id : "T2",
50885
+ TEAM_2_MANAGER : {
50886
+ "@odata.etag" : "etagM2",
50887
+ ID : "M2",
50888
+ TEAM_ID : "T2"
50889
+ }
50890
+ }
50891
+ });
50892
+ });
50893
+ });
50894
+
49920
50895
  //*********************************************************************************************
49921
50896
  // Scenario: A deep create of a sales order with items is tried, but there is an ODCB w/o path
49922
50897
  // (w/ or w/o own cache) in between. A non-deep create however must work.
@@ -52084,7 +53059,25 @@ sap.ui.define([
52084
53059
  headers : {"If-Match" : "ETag"},
52085
53060
  method : "DELETE",
52086
53061
  url : "Artists(ArtistID='42',IsActiveEntity=false)"
52087
- });
53062
+ }, undefined, {
53063
+ "sap-messages" : JSON.stringify([{
53064
+ code : "foo-42",
53065
+ message : "What a nice name!",
53066
+ numericSeverity : 2,
53067
+ target : "Name"
53068
+ }])
53069
+ })
53070
+ .expectMessages([{
53071
+ message : sMessage1,
53072
+ target : "/Artists(ArtistID='42',IsActiveEntity=false)/Name",
53073
+ type : "Success"
53074
+ }, {
53075
+ code : "foo-42",
53076
+ message : "What a nice name!",
53077
+ persistent : true,
53078
+ target : "/Artists(ArtistID='42',IsActiveEntity=false)/Name",
53079
+ type : "Information"
53080
+ }]);
52088
53081
 
52089
53082
  return Promise.all([
52090
53083
  // code under test
@@ -52102,6 +53095,40 @@ sap.ui.define([
52102
53095
  return that.waitForChanges(assert, "show active");
52103
53096
  }).then(function () {
52104
53097
  return that.checkValueState(assert, that.oView.byId("name"), "None", "");
53098
+ }).then(function () {
53099
+ that.oLogMock.expects("error")
53100
+ .withArgs("Failed to delete /Artists(ArtistID='42',IsActiveEntity=false)");
53101
+ that.expectRequest({
53102
+ headers : {"If-Match" : "ETag"},
53103
+ method : "DELETE",
53104
+ url : "Artists(ArtistID='42',IsActiveEntity=false)"
53105
+ }, createErrorInsideBatch({target : "ArtistID"}))
53106
+ .expectMessages([{
53107
+ message : sMessage1,
53108
+ target : "/Artists(ArtistID='42',IsActiveEntity=false)/Name",
53109
+ type : "Success"
53110
+ }, {
53111
+ code : "foo-42",
53112
+ message : "What a nice name!",
53113
+ persistent : true,
53114
+ target : "/Artists(ArtistID='42',IsActiveEntity=false)/Name",
53115
+ type : "Information"
53116
+ }, {
53117
+ code : "CODE",
53118
+ message : "Request intentionally failed",
53119
+ persistent : true,
53120
+ target : "/Artists(ArtistID='42',IsActiveEntity=false)/ArtistID",
53121
+ technical : true,
53122
+ type : "Error"
53123
+ }]);
53124
+
53125
+ return Promise.all([
53126
+ // code under test
53127
+ oModel.delete(oDraftContext).then(mustFail(assert), function (oError) {
53128
+ assert.strictEqual(oError.message, "Request intentionally failed");
53129
+ }),
53130
+ that.waitForChanges(assert, "delete again")
53131
+ ]);
52105
53132
  }).then(function () {
52106
53133
  that.expectMessages([]);
52107
53134