@openui5/sap.ui.core 1.122.1 → 1.123.1

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 (534) hide show
  1. package/.dtsgenrc +7 -1
  2. package/.eslintrc.json +3 -0
  3. package/package.json +1 -1
  4. package/src/jquery.sap.global.js +1 -17
  5. package/src/jquery.sap.properties.js +1 -1
  6. package/src/jquery.sap.resources.js +1 -1
  7. package/src/jquery.sap.script.js +1 -1
  8. package/src/jquery.sap.storage.js +3 -3
  9. package/src/sap/base/Event.js +1 -1
  10. package/src/sap/base/Eventing.js +1 -1
  11. package/src/sap/base/config.js +1 -1
  12. package/src/sap/base/future.js +3 -1
  13. package/src/sap/base/i18n/Formatting.js +119 -94
  14. package/src/sap/base/i18n/LanguageTag.js +1 -1
  15. package/src/sap/base/i18n/date/TimezoneUtils.js +1 -1
  16. package/src/sap/base/util/restricted/_CancelablePromise.js +1 -1
  17. package/src/sap/base/util/restricted/_castArray.js +1 -1
  18. package/src/sap/base/util/restricted/_compact.js +1 -1
  19. package/src/sap/base/util/restricted/_curry.js +1 -1
  20. package/src/sap/base/util/restricted/_debounce.js +1 -1
  21. package/src/sap/base/util/restricted/_difference.js +1 -1
  22. package/src/sap/base/util/restricted/_differenceBy.js +1 -1
  23. package/src/sap/base/util/restricted/_differenceWith.js +1 -1
  24. package/src/sap/base/util/restricted/_flatMap.js +1 -1
  25. package/src/sap/base/util/restricted/_flatMapDeep.js +1 -1
  26. package/src/sap/base/util/restricted/_flatMapDepth.js +1 -1
  27. package/src/sap/base/util/restricted/_flatten.js +1 -1
  28. package/src/sap/base/util/restricted/_flattenDeep.js +1 -1
  29. package/src/sap/base/util/restricted/_flattenDepth.js +1 -1
  30. package/src/sap/base/util/restricted/_intersection.js +1 -1
  31. package/src/sap/base/util/restricted/_intersectionBy.js +1 -1
  32. package/src/sap/base/util/restricted/_intersectionWith.js +1 -1
  33. package/src/sap/base/util/restricted/_isEqual.js +1 -1
  34. package/src/sap/base/util/restricted/_isEqualWith.js +1 -1
  35. package/src/sap/base/util/restricted/_isNil.js +1 -1
  36. package/src/sap/base/util/restricted/_max.js +1 -1
  37. package/src/sap/base/util/restricted/_merge.js +1 -1
  38. package/src/sap/base/util/restricted/_mergeWith.js +1 -1
  39. package/src/sap/base/util/restricted/_min.js +1 -1
  40. package/src/sap/base/util/restricted/_omit.js +1 -1
  41. package/src/sap/base/util/restricted/_pick.js +1 -1
  42. package/src/sap/base/util/restricted/_pickBy.js +1 -1
  43. package/src/sap/base/util/restricted/_throttle.js +1 -1
  44. package/src/sap/base/util/restricted/_toArray.js +1 -1
  45. package/src/sap/base/util/restricted/_union.js +1 -1
  46. package/src/sap/base/util/restricted/_unionBy.js +1 -1
  47. package/src/sap/base/util/restricted/_unionWith.js +1 -1
  48. package/src/sap/base/util/restricted/_uniq.js +1 -1
  49. package/src/sap/base/util/restricted/_uniqBy.js +1 -1
  50. package/src/sap/base/util/restricted/_uniqWith.js +1 -1
  51. package/src/sap/base/util/restricted/_without.js +1 -1
  52. package/src/sap/base/util/restricted/_xor.js +1 -1
  53. package/src/sap/base/util/restricted/_xorBy.js +1 -1
  54. package/src/sap/base/util/restricted/_xorWith.js +1 -1
  55. package/src/sap/base/util/restricted/_zipObject.js +1 -1
  56. package/src/sap/base/util/restricted/_zipObjectDeep.js +1 -1
  57. package/src/sap/ui/Device.js +3 -3
  58. package/src/sap/ui/Global.js +7 -4
  59. package/src/sap/ui/base/BindingInfo.js +22 -0
  60. package/src/sap/ui/base/Event.js +1 -1
  61. package/src/sap/ui/base/EventProvider.js +1 -1
  62. package/src/sap/ui/base/Interface.js +1 -1
  63. package/src/sap/ui/base/ManagedObject.js +5 -14
  64. package/src/sap/ui/base/ManagedObjectMetadata.js +1 -1
  65. package/src/sap/ui/base/Metadata.js +15 -14
  66. package/src/sap/ui/base/Object.js +1 -1
  67. package/src/sap/ui/base/ObjectPool.js +1 -1
  68. package/src/sap/ui/core/.library +1 -1
  69. package/src/sap/ui/core/BusyIndicator.js +1 -1
  70. package/src/sap/ui/core/Component.js +17 -16
  71. package/src/sap/ui/core/ComponentContainer.js +1 -1
  72. package/src/sap/ui/core/ComponentMetadata.js +1 -1
  73. package/src/sap/ui/core/ComponentSupport.js +1 -1
  74. package/src/sap/ui/core/Configuration.js +53 -18
  75. package/src/sap/ui/core/Control.js +1 -1
  76. package/src/sap/ui/core/Core.js +58 -21
  77. package/src/sap/ui/core/CustomData.js +1 -1
  78. package/src/sap/ui/core/DeclarativeSupport.js +1 -1
  79. package/src/sap/ui/core/Element.js +1 -1
  80. package/src/sap/ui/core/ElementMetadata.js +1 -1
  81. package/src/sap/ui/core/EnabledPropagator.js +1 -1
  82. package/src/sap/ui/core/EventBus.js +6 -2
  83. package/src/sap/ui/core/Fragment.js +10 -5
  84. package/src/sap/ui/core/HTML.js +1 -1
  85. package/src/sap/ui/core/History.js +1 -1
  86. package/src/sap/ui/core/Icon.js +1 -1
  87. package/src/sap/ui/core/IndicationColorSupport.js +1 -1
  88. package/src/sap/ui/core/IntervalTrigger.js +1 -1
  89. package/src/sap/ui/core/InvisibleMessage.js +1 -1
  90. package/src/sap/ui/core/InvisibleRenderer.js +1 -1
  91. package/src/sap/ui/core/InvisibleText.js +1 -1
  92. package/src/sap/ui/core/Item.js +1 -1
  93. package/src/sap/ui/core/LabelEnablement.js +1 -1
  94. package/src/sap/ui/core/LayoutData.js +1 -1
  95. package/src/sap/ui/core/ListItem.js +1 -1
  96. package/src/sap/ui/core/LocalBusyIndicator.js +1 -1
  97. package/src/sap/ui/core/Locale.js +1 -1
  98. package/src/sap/ui/core/LocaleData.js +37 -21
  99. package/src/sap/ui/core/Manifest.js +1 -1
  100. package/src/sap/ui/core/Message.js +1 -1
  101. package/src/sap/ui/core/RenderManager.js +7 -1
  102. package/src/sap/ui/core/Renderer.js +4 -1
  103. package/src/sap/ui/core/ResizeHandler.js +1 -1
  104. package/src/sap/ui/core/ScrollBar.js +2 -2
  105. package/src/sap/ui/core/SeparatorItem.js +1 -1
  106. package/src/sap/ui/core/Title.js +1 -1
  107. package/src/sap/ui/core/TooltipBase.js +1 -1
  108. package/src/sap/ui/core/UIArea.js +37 -47
  109. package/src/sap/ui/core/UIComponent.js +1 -1
  110. package/src/sap/ui/core/UIComponentMetadata.js +1 -1
  111. package/src/sap/ui/core/ValueStateSupport.js +1 -1
  112. package/src/sap/ui/core/VariantLayoutData.js +1 -1
  113. package/src/sap/ui/core/XMLComposite.js +1 -1
  114. package/src/sap/ui/core/XMLCompositeMetadata.js +1 -1
  115. package/src/sap/ui/core/XMLTemplateProcessor.js +12 -0
  116. package/src/sap/ui/core/_IconRegistry.js +1 -0
  117. package/src/sap/ui/core/date/UI5Date.js +1 -1
  118. package/src/sap/ui/core/delegate/ItemNavigation.js +1 -1
  119. package/src/sap/ui/core/delegate/ScrollEnablement.js +2 -2
  120. package/src/sap/ui/core/dnd/DragDropBase.js +1 -1
  121. package/src/sap/ui/core/dnd/DragDropInfo.js +1 -1
  122. package/src/sap/ui/core/dnd/DragInfo.js +1 -1
  123. package/src/sap/ui/core/dnd/DropInfo.js +1 -1
  124. package/src/sap/ui/core/format/FormatUtils.js +1 -1
  125. package/src/sap/ui/core/format/NumberFormat.js +28 -3
  126. package/src/sap/ui/core/format/TimezoneUtil.js +1 -1
  127. package/src/sap/ui/core/getCompatibilityVersion.js +6 -2
  128. package/src/sap/ui/core/hyphenation/Hyphenation.js +1 -1
  129. package/src/sap/ui/core/library.js +3 -3
  130. package/src/sap/ui/core/message/ControlMessageProcessor.js +1 -1
  131. package/src/sap/ui/core/message/Message.js +1 -1
  132. package/src/sap/ui/core/message/MessageManager.js +1 -1
  133. package/src/sap/ui/core/message/MessageParser.js +1 -1
  134. package/src/sap/ui/core/message/MessageProcessor.js +1 -1
  135. package/src/sap/ui/core/mvc/HTMLView.js +1 -1
  136. package/src/sap/ui/core/mvc/JSONView.js +1 -1
  137. package/src/sap/ui/core/mvc/JSView.js +1 -1
  138. package/src/sap/ui/core/mvc/TemplateView.js +1 -1
  139. package/src/sap/ui/core/mvc/View.js +12 -7
  140. package/src/sap/ui/core/mvc/XMLView.js +1 -1
  141. package/src/sap/ui/core/plugin/DeclarativeSupport.js +1 -1
  142. package/src/sap/ui/core/plugin/LessSupport.js +1 -1
  143. package/src/sap/ui/core/plugin/TemplatingSupport.js +1 -1
  144. package/src/sap/ui/core/postmessage/Bus.js +1 -1
  145. package/src/sap/ui/core/postmessage/confirmationDialog.js +1 -1
  146. package/src/sap/ui/core/rules/CoreHelper.support.js +2 -3
  147. package/src/sap/ui/core/rules/Misc.support.js +3 -12
  148. package/src/sap/ui/core/rules/Theming.support.js +5 -9
  149. package/src/sap/ui/core/search/OpenSearchProvider.js +1 -1
  150. package/src/sap/ui/core/search/SearchProvider.js +1 -1
  151. package/src/sap/ui/core/service/Service.js +1 -1
  152. package/src/sap/ui/core/service/ServiceFactory.js +1 -1
  153. package/src/sap/ui/core/service/ServiceFactoryRegistry.js +1 -1
  154. package/src/sap/ui/core/support/Plugin.js +1 -1
  155. package/src/sap/ui/core/support/Support.js +1 -20
  156. package/src/sap/ui/core/support/plugins/ControlTree.js +1 -1
  157. package/src/sap/ui/core/support/plugins/Interaction.js +1 -1
  158. package/src/sap/ui/core/support/plugins/LocalStorage.js +1 -1
  159. package/src/sap/ui/core/support/plugins/Performance.js +1 -1
  160. package/src/sap/ui/core/support/plugins/Selector.js +1 -1
  161. package/src/sap/ui/core/support/plugins/TechInfo.js +1 -1
  162. package/src/sap/ui/core/support/plugins/Trace.js +1 -1
  163. package/src/sap/ui/core/support/plugins/ViewInfo.js +1 -1
  164. package/src/sap/ui/core/themes/base/.theming +3 -1
  165. package/src/sap/ui/core/themes/base/fonts/SAP-icons.ttf +0 -0
  166. package/src/sap/ui/core/themes/base/fonts/SAP-icons.woff2 +0 -0
  167. package/src/sap/ui/core/theming/Parameters.js +5 -1
  168. package/src/sap/ui/core/tmpl/DOMAttribute.js +1 -1
  169. package/src/sap/ui/core/tmpl/DOMElement.js +1 -1
  170. package/src/sap/ui/core/tmpl/HandlebarsTemplate.js +1 -1
  171. package/src/sap/ui/core/tmpl/Template.js +1 -1
  172. package/src/sap/ui/core/tmpl/TemplateControl.js +1 -1
  173. package/src/sap/ui/core/util/AsyncHintsHelper.js +1 -1
  174. package/src/sap/ui/core/util/Export.js +2 -2
  175. package/src/sap/ui/core/util/ExportCell.js +2 -2
  176. package/src/sap/ui/core/util/ExportColumn.js +2 -2
  177. package/src/sap/ui/core/util/ExportRow.js +2 -2
  178. package/src/sap/ui/core/util/ExportType.js +2 -2
  179. package/src/sap/ui/core/util/ExportTypeCSV.js +2 -2
  180. package/src/sap/ui/core/util/File.js +1 -1
  181. package/src/sap/ui/core/util/LibraryInfo.js +1 -1
  182. package/src/sap/ui/core/util/MockServer.js +1 -1
  183. package/src/sap/ui/core/util/PasteHelper.js +1 -1
  184. package/src/sap/ui/core/util/XMLPreprocessor.js +8 -13
  185. package/src/sap/ui/core/util/serializer/HTMLViewSerializer.js +1 -1
  186. package/src/sap/ui/core/util/serializer/Serializer.js +1 -1
  187. package/src/sap/ui/core/util/serializer/ViewSerializer.js +1 -1
  188. package/src/sap/ui/core/util/serializer/XMLViewSerializer.js +1 -1
  189. package/src/sap/ui/core/util/serializer/delegate/Delegate.js +1 -1
  190. package/src/sap/ui/core/util/serializer/delegate/HTML.js +1 -1
  191. package/src/sap/ui/core/util/serializer/delegate/XML.js +1 -1
  192. package/src/sap/ui/core/webc/WebComponent.js +1 -1
  193. package/src/sap/ui/core/webc/WebComponentMetadata.js +1 -1
  194. package/src/sap/ui/core/ws/ReadyState.js +1 -1
  195. package/src/sap/ui/core/ws/SapPcpWebSocket.js +1 -1
  196. package/src/sap/ui/core/ws/WebSocket.js +1 -1
  197. package/src/sap/ui/debug/ControlTree.js +1 -1
  198. package/src/sap/ui/debug/DebugEnv.js +1 -1
  199. package/src/sap/ui/debug/PropertyList.js +1 -1
  200. package/src/sap/ui/dom/jquery/Aria.js +19 -0
  201. package/src/sap/ui/events/jquery/EventExtension.js +4 -3
  202. package/src/sap/ui/model/ClientModel.js +1 -1
  203. package/src/sap/ui/model/CompositeDataState.js +1 -1
  204. package/src/sap/ui/model/CompositeType.js +4 -4
  205. package/src/sap/ui/model/DataState.js +2 -2
  206. package/src/sap/ui/model/ManagedObjectBindingSupport.js +22 -33
  207. package/src/sap/ui/model/MetaModel.js +1 -1
  208. package/src/sap/ui/model/Model.js +1 -1
  209. package/src/sap/ui/model/SelectionModel.js +1 -1
  210. package/src/sap/ui/model/SimpleType.js +1 -1
  211. package/src/sap/ui/model/TreeAutoExpandMode.js +1 -1
  212. package/src/sap/ui/model/Type.js +1 -1
  213. package/src/sap/ui/model/analytics/AnalyticalVersionInfo.js +1 -1
  214. package/src/sap/ui/model/controlhelper/TreeBindingProxy.js +7 -1
  215. package/src/sap/ui/model/json/JSONModel.js +1 -1
  216. package/src/sap/ui/model/message/MessageModel.js +1 -1
  217. package/src/sap/ui/model/odata/AnnotationHelper.js +11 -8
  218. package/src/sap/ui/model/odata/ODataAnnotations.js +1 -1
  219. package/src/sap/ui/model/odata/ODataExpressionAddons.js +21 -0
  220. package/src/sap/ui/model/odata/ODataMessageParser.js +1 -1
  221. package/src/sap/ui/model/odata/ODataMetaModel.js +1 -1
  222. package/src/sap/ui/model/odata/ODataMetadata.js +1 -1
  223. package/src/sap/ui/model/odata/ODataModel.js +1 -1
  224. package/src/sap/ui/model/odata/type/Boolean.js +1 -1
  225. package/src/sap/ui/model/odata/type/Byte.js +1 -1
  226. package/src/sap/ui/model/odata/type/Currency.js +1 -1
  227. package/src/sap/ui/model/odata/type/Date.js +1 -1
  228. package/src/sap/ui/model/odata/type/DateTime.js +1 -1
  229. package/src/sap/ui/model/odata/type/DateTimeBase.js +1 -1
  230. package/src/sap/ui/model/odata/type/DateTimeOffset.js +1 -1
  231. package/src/sap/ui/model/odata/type/DateTimeWithTimezone.js +1 -1
  232. package/src/sap/ui/model/odata/type/Decimal.js +1 -1
  233. package/src/sap/ui/model/odata/type/Double.js +1 -1
  234. package/src/sap/ui/model/odata/type/Guid.js +1 -1
  235. package/src/sap/ui/model/odata/type/Int.js +1 -1
  236. package/src/sap/ui/model/odata/type/Int16.js +1 -1
  237. package/src/sap/ui/model/odata/type/Int32.js +1 -1
  238. package/src/sap/ui/model/odata/type/Int64.js +1 -1
  239. package/src/sap/ui/model/odata/type/ODataType.js +1 -1
  240. package/src/sap/ui/model/odata/type/Raw.js +1 -1
  241. package/src/sap/ui/model/odata/type/SByte.js +1 -1
  242. package/src/sap/ui/model/odata/type/Single.js +1 -1
  243. package/src/sap/ui/model/odata/type/Stream.js +1 -1
  244. package/src/sap/ui/model/odata/type/String.js +1 -1
  245. package/src/sap/ui/model/odata/type/Time.js +1 -1
  246. package/src/sap/ui/model/odata/type/TimeOfDay.js +1 -1
  247. package/src/sap/ui/model/odata/type/Unit.js +1 -1
  248. package/src/sap/ui/model/odata/v2/Context.js +1 -1
  249. package/src/sap/ui/model/odata/v2/ODataAnnotations.js +1 -1
  250. package/src/sap/ui/model/odata/v2/ODataModel.js +17 -48
  251. package/src/sap/ui/model/odata/v2/ODataTreeBinding.js +1 -1
  252. package/src/sap/ui/model/odata/v4/AnnotationHelper.js +2 -0
  253. package/src/sap/ui/model/odata/v4/Context.js +66 -22
  254. package/src/sap/ui/model/odata/v4/ODataBinding.js +10 -11
  255. package/src/sap/ui/model/odata/v4/ODataContextBinding.js +207 -180
  256. package/src/sap/ui/model/odata/v4/ODataListBinding.js +75 -52
  257. package/src/sap/ui/model/odata/v4/ODataMetaModel.js +9 -11
  258. package/src/sap/ui/model/odata/v4/ODataModel.js +34 -35
  259. package/src/sap/ui/model/odata/v4/ODataParentBinding.js +9 -9
  260. package/src/sap/ui/model/odata/v4/ODataPropertyBinding.js +20 -8
  261. package/src/sap/ui/model/odata/v4/SubmitMode.js +1 -1
  262. package/src/sap/ui/model/odata/v4/lib/_AggregationCache.js +126 -46
  263. package/src/sap/ui/model/odata/v4/lib/_AggregationHelper.js +56 -11
  264. package/src/sap/ui/model/odata/v4/lib/_Cache.js +21 -34
  265. package/src/sap/ui/model/odata/v4/lib/_Helper.js +16 -27
  266. package/src/sap/ui/model/odata/v4/lib/_MetadataConverter.js +2 -6
  267. package/src/sap/ui/model/odata/v4/lib/_MinMaxHelper.js +1 -1
  268. package/src/sap/ui/model/odata/v4/lib/_Parser.js +6 -5
  269. package/src/sap/ui/model/odata/v4/lib/_Requestor.js +49 -38
  270. package/src/sap/ui/model/odata/v4/lib/_TreeState.js +75 -24
  271. package/src/sap/ui/model/odata/v4/lib/_V2MetadataConverter.js +3 -4
  272. package/src/sap/ui/model/odata/v4/lib/_V2Requestor.js +4 -12
  273. package/src/sap/ui/model/odata/v4/lib/_V4MetadataConverter.js +1 -1
  274. package/src/sap/ui/model/resource/ResourceModel.js +1 -1
  275. package/src/sap/ui/model/type/Boolean.js +1 -1
  276. package/src/sap/ui/model/type/Currency.js +48 -4
  277. package/src/sap/ui/model/type/Date.js +1 -1
  278. package/src/sap/ui/model/type/DateInterval.js +1 -1
  279. package/src/sap/ui/model/type/DateTime.js +1 -1
  280. package/src/sap/ui/model/type/DateTimeInterval.js +1 -1
  281. package/src/sap/ui/model/type/FileSize.js +1 -1
  282. package/src/sap/ui/model/type/Float.js +1 -1
  283. package/src/sap/ui/model/type/Integer.js +1 -1
  284. package/src/sap/ui/model/type/String.js +1 -1
  285. package/src/sap/ui/model/type/Time.js +1 -1
  286. package/src/sap/ui/model/type/TimeInterval.js +1 -1
  287. package/src/sap/ui/model/type/Unit.js +5 -4
  288. package/src/sap/ui/model/xml/XMLModel.js +1 -1
  289. package/src/sap/ui/qunit/utils/ControlIterator.js +1 -1
  290. package/src/sap/ui/qunit/utils/MemoryLeakCheck.js +4 -1
  291. package/src/sap/ui/test/ModuleTracking.js +46 -0
  292. package/src/sap/ui/test/OpaBuilder.js +19 -19
  293. package/src/sap/ui/test/autowaiter/_jsAnimationWaiter.js +39 -6
  294. package/src/sap/ui/test/generic/TestBase.js +1 -1
  295. package/src/sap/ui/util/Storage.js +1 -1
  296. package/src/sap/ui/util/_enforceNoReturnValue.js +3 -1
  297. package/src/ui5loader-autoconfig.js +22 -16
  298. package/src/ui5loader.js +38 -1
  299. package/test/sap/ui/core/demokit/docuindex.json +17 -6
  300. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/BasicMessages/Component.js +1 -1
  301. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/BasicMessages/Controller.controller.js +30 -47
  302. package/test/sap/ui/core/demokit/sample/Messaging/BasicMessages/MessagePopover.fragment.xml +13 -0
  303. package/test/sap/ui/core/demokit/sample/Messaging/BasicMessages/View.view.xml +135 -0
  304. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/BasicMessages/manifest.json +2 -2
  305. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/BasicODataMessages/Component.js +1 -1
  306. package/test/sap/ui/core/demokit/sample/Messaging/BasicODataMessages/Controller.controller.js +58 -0
  307. package/test/sap/ui/core/demokit/sample/Messaging/BasicODataMessages/MessagePopover.fragment.xml +13 -0
  308. package/test/sap/ui/core/demokit/sample/Messaging/BasicODataMessages/View.view.xml +57 -0
  309. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/BasicODataMessages/localService/mockserver.js +11 -13
  310. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/BasicODataMessages/manifest.json +2 -2
  311. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/Component.js +1 -1
  312. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/manifest.json +2 -1
  313. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/package.json +1 -1
  314. package/test/sap/ui/core/demokit/sample/Messaging/ODataBackendMessagesComp/ui5.yaml +11 -0
  315. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/webapp/Component.js +2 -2
  316. package/test/sap/ui/core/demokit/sample/Messaging/ODataBackendMessagesComp/webapp/controller/App.controller.js +12 -0
  317. package/test/sap/ui/core/demokit/sample/Messaging/ODataBackendMessagesComp/webapp/controller/BaseController.js +41 -0
  318. package/test/sap/ui/core/demokit/sample/Messaging/ODataBackendMessagesComp/webapp/controller/Employee.controller.js +54 -0
  319. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/webapp/controller/NotFound.controller.js +9 -11
  320. package/test/sap/ui/core/demokit/sample/Messaging/ODataBackendMessagesComp/webapp/fragment/MessagePopover.fragment.xml +13 -0
  321. package/test/sap/ui/core/demokit/sample/Messaging/ODataBackendMessagesComp/webapp/i18n/i18n.properties +9 -0
  322. package/test/sap/ui/core/demokit/sample/Messaging/ODataBackendMessagesComp/webapp/index.html +20 -0
  323. package/test/sap/ui/core/demokit/sample/Messaging/ODataBackendMessagesComp/webapp/index.js +16 -0
  324. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/webapp/localService/mockserver.js +27 -27
  325. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/webapp/manifest.json +7 -4
  326. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/webapp/view/App.view.xml +1 -1
  327. package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/webapp/view/Employee.view.xml +6 -6
  328. package/test/sap/ui/core/demokit/sample/Messaging/ODataBackendMessagesComp/webapp/view/NotFound.view.xml +13 -0
  329. package/test/sap/ui/core/demokit/sample/ViewTemplate/types/Types.controller.js +1 -1
  330. package/test/sap/ui/core/demokit/sample/common/Helper.js +8 -9
  331. package/test/sap/ui/core/demokit/sample/common/SandboxModelHelper.js +1 -1
  332. package/test/sap/ui/core/demokit/sample/gherkin/GherkinWithOPA5/GherkinTestRunner.html +2 -2
  333. package/test/sap/ui/core/demokit/sample/gherkin/GherkinWithPageObjects/GherkinTestRunner.html +2 -2
  334. package/test/sap/ui/core/demokit/sample/gherkin/GherkinWithQUnit/GherkinTestRunner.html +2 -2
  335. package/test/sap/ui/core/demokit/sample/gherkin/GherkinWithQUnit/Steps.js +4 -5
  336. package/test/sap/ui/core/demokit/sample/gherkin/GherkinWithUIComponent/GherkinTestRunner.html +2 -2
  337. package/test/sap/ui/core/demokit/sample/matcher/BindingPath/ui5.yaml +1 -1
  338. package/test/sap/ui/core/demokit/sample/matcher/Descendant/ui5.yaml +1 -1
  339. package/test/sap/ui/core/demokit/sample/matcher/I18NText/ui5.yaml +1 -1
  340. package/test/sap/ui/core/demokit/sample/matcher/LabelFor/ui5.yaml +1 -1
  341. package/test/sap/ui/core/demokit/sample/odata/v2/AutoExpand/AutoExpand.view.xml +1 -0
  342. package/test/sap/ui/core/demokit/sample/odata/v4/ConsumeV2Service/Main.controller.js +1 -1
  343. package/test/sap/ui/core/demokit/sample/odata/v4/Draft/ObjectPage.controller.js +2 -2
  344. package/test/sap/ui/core/demokit/sample/odata/v4/FlatDataAggregation/FlatDataAggregation.controller.js +1 -1
  345. package/test/sap/ui/core/demokit/sample/odata/v4/FlexibleColumnLayout/Main.controller.js +1 -1
  346. package/test/sap/ui/core/demokit/sample/odata/v4/ListBinding/MIT.ListBinding.html +1 -1
  347. package/test/sap/ui/core/demokit/sample/odata/v4/ListBinding/Main.controller.js +5 -7
  348. package/test/sap/ui/core/demokit/sample/odata/v4/ListBinding/Main.view.xml +2 -2
  349. package/test/sap/ui/core/demokit/sample/odata/v4/ListBindingTemplate/MIT.ListBindingTemplate.html +1 -1
  350. package/test/sap/ui/core/demokit/sample/odata/v4/MultipleInlineCreationRowsGrid/Main.controller.js +3 -3
  351. package/test/sap/ui/core/demokit/sample/odata/v4/MultipleInlineCreationRowsGrid/Main.view.xml +6 -5
  352. package/test/sap/ui/core/demokit/sample/odata/v4/MusicArtists/ObjectPage.controller.js +5 -7
  353. package/test/sap/ui/core/demokit/sample/odata/v4/Products/MIT.Products.html +2 -2
  354. package/test/sap/ui/core/demokit/sample/odata/v4/Products/pages/Main.js +1 -1
  355. package/test/sap/ui/core/demokit/sample/odata/v4/RecursiveHierarchy/SandboxModel.js +27 -9
  356. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrderTP100_V2/MIT.SalesOrderTP100.html +1 -1
  357. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrderTP100_V4/MIT.SalesOrderTP100.html +1 -1
  358. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/MIT.Basics.html +1 -1
  359. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/MIT.SalesOrderAdditionalTargets.html +1 -1
  360. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/MIT.SalesOrderCreate.html +1 -1
  361. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/MIT.SalesOrderCreateMultiple.html +1 -1
  362. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/MIT.SalesOrderCreateRelative.html +1 -1
  363. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/MIT.SalesOrderMessageHandling.html +3 -3
  364. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/Main.controller.js +5 -5
  365. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/Main.view.xml +3 -3
  366. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/pages/Main.js +7 -9
  367. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrders/tests/MessageHandling.js +3 -3
  368. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrdersRTATest/MIT.RTA.html +2 -2
  369. package/test/sap/ui/core/demokit/sample/odata/v4/SalesOrdersTemplate/MIT.SalesOrdersTemplate.html +1 -1
  370. package/test/sap/ui/core/demokit/sample/odata/v4/Sticky/MIT.Sticky.html +3 -3
  371. package/test/sap/ui/core/demokit/sample/odata/v4/Sticky/Main.controller.js +3 -3
  372. package/test/sap/ui/core/demokit/sample/odata/v4/Sticky/pages/Main.js +1 -1
  373. package/test/sap/ui/core/demokit/tutorial/databinding/01/ui5.yaml +1 -1
  374. package/test/sap/ui/core/demokit/tutorial/databinding/02/ui5.yaml +1 -1
  375. package/test/sap/ui/core/demokit/tutorial/databinding/03/ui5.yaml +1 -1
  376. package/test/sap/ui/core/demokit/tutorial/databinding/04/ui5.yaml +1 -1
  377. package/test/sap/ui/core/demokit/tutorial/databinding/05/ui5.yaml +1 -1
  378. package/test/sap/ui/core/demokit/tutorial/databinding/06/ui5.yaml +1 -1
  379. package/test/sap/ui/core/demokit/tutorial/databinding/07/ui5.yaml +1 -1
  380. package/test/sap/ui/core/demokit/tutorial/databinding/08/ui5.yaml +1 -1
  381. package/test/sap/ui/core/demokit/tutorial/databinding/09/ui5.yaml +1 -1
  382. package/test/sap/ui/core/demokit/tutorial/databinding/10/ui5.yaml +1 -1
  383. package/test/sap/ui/core/demokit/tutorial/databinding/11/ui5.yaml +1 -1
  384. package/test/sap/ui/core/demokit/tutorial/databinding/12/ui5.yaml +1 -1
  385. package/test/sap/ui/core/demokit/tutorial/databinding/13/ui5.yaml +1 -1
  386. package/test/sap/ui/core/demokit/tutorial/databinding/14/ui5.yaml +1 -1
  387. package/test/sap/ui/core/demokit/tutorial/databinding/15/ui5.yaml +1 -1
  388. package/test/sap/ui/core/demokit/tutorial/mockserver/01/ui5.yaml +1 -1
  389. package/test/sap/ui/core/demokit/tutorial/mockserver/02/ui5.yaml +1 -1
  390. package/test/sap/ui/core/demokit/tutorial/mockserver/03/ui5.yaml +1 -1
  391. package/test/sap/ui/core/demokit/tutorial/mockserver/04/ui5.yaml +1 -1
  392. package/test/sap/ui/core/demokit/tutorial/navigation/01/ui5.yaml +1 -1
  393. package/test/sap/ui/core/demokit/tutorial/navigation/02/ui5.yaml +1 -1
  394. package/test/sap/ui/core/demokit/tutorial/navigation/03/ui5.yaml +1 -1
  395. package/test/sap/ui/core/demokit/tutorial/navigation/04/ui5.yaml +1 -1
  396. package/test/sap/ui/core/demokit/tutorial/navigation/05/ui5.yaml +1 -1
  397. package/test/sap/ui/core/demokit/tutorial/navigation/06/ui5.yaml +1 -1
  398. package/test/sap/ui/core/demokit/tutorial/navigation/07/ui5.yaml +1 -1
  399. package/test/sap/ui/core/demokit/tutorial/navigation/08/ui5.yaml +1 -1
  400. package/test/sap/ui/core/demokit/tutorial/navigation/09/ui5.yaml +1 -1
  401. package/test/sap/ui/core/demokit/tutorial/navigation/10/ui5.yaml +1 -1
  402. package/test/sap/ui/core/demokit/tutorial/navigation/11/ui5.yaml +1 -1
  403. package/test/sap/ui/core/demokit/tutorial/navigation/12/ui5.yaml +1 -1
  404. package/test/sap/ui/core/demokit/tutorial/navigation/13/ui5.yaml +1 -1
  405. package/test/sap/ui/core/demokit/tutorial/navigation/14/ui5.yaml +1 -1
  406. package/test/sap/ui/core/demokit/tutorial/navigation/15/ui5.yaml +1 -1
  407. package/test/sap/ui/core/demokit/tutorial/navigation/16/ui5.yaml +1 -1
  408. package/test/sap/ui/core/demokit/tutorial/navigation/17/ui5.yaml +1 -1
  409. package/test/sap/ui/core/demokit/tutorial/odatav4/01/ui5.yaml +1 -1
  410. package/test/sap/ui/core/demokit/tutorial/odatav4/02/ui5.yaml +1 -1
  411. package/test/sap/ui/core/demokit/tutorial/odatav4/03/ui5.yaml +1 -1
  412. package/test/sap/ui/core/demokit/tutorial/odatav4/04/ui5.yaml +1 -1
  413. package/test/sap/ui/core/demokit/tutorial/odatav4/05/ui5.yaml +1 -1
  414. package/test/sap/ui/core/demokit/tutorial/odatav4/06/ui5.yaml +1 -1
  415. package/test/sap/ui/core/demokit/tutorial/odatav4/06/webapp/localService/mockserver.js +1 -1
  416. package/test/sap/ui/core/demokit/tutorial/odatav4/07/ui5.yaml +1 -1
  417. package/test/sap/ui/core/demokit/tutorial/odatav4/07/webapp/localService/mockserver.js +1 -1
  418. package/test/sap/ui/core/demokit/tutorial/odatav4/08/ui5.yaml +1 -1
  419. package/test/sap/ui/core/demokit/tutorial/odatav4/08/webapp/controller/App.controller.js +1 -1
  420. package/test/sap/ui/core/demokit/tutorial/odatav4/08/webapp/localService/mockserver.js +1 -1
  421. package/test/sap/ui/core/demokit/tutorial/odatav4/09/ui5.yaml +1 -1
  422. package/test/sap/ui/core/demokit/tutorial/odatav4/09/webapp/controller/App.controller.js +1 -1
  423. package/test/sap/ui/core/demokit/tutorial/odatav4/09/webapp/localService/mockserver.js +1 -1
  424. package/test/sap/ui/core/demokit/tutorial/odatav4/10/ui5.yaml +1 -1
  425. package/test/sap/ui/core/demokit/tutorial/odatav4/10/webapp/controller/App.controller.js +1 -1
  426. package/test/sap/ui/core/demokit/tutorial/odatav4/10/webapp/localService/mockserver.js +1 -1
  427. package/test/sap/ui/core/demokit/tutorial/odatav4/11/ui5.yaml +1 -1
  428. package/test/sap/ui/core/demokit/tutorial/odatav4/11/webapp/controller/App.controller.js +1 -1
  429. package/test/sap/ui/core/demokit/tutorial/odatav4/11/webapp/localService/mockserver.js +1 -1
  430. package/test/sap/ui/core/demokit/tutorial/troubleshooting/01/ui5.yaml +1 -1
  431. package/test/sap/ui/core/internal/samples/odata/v2/Products/Main.view.xml +1 -1
  432. package/test/sap/ui/core/qunit/CustomStyleClassSupport.qunit.js +12 -3
  433. package/test/sap/ui/core/qunit/CustomThemeFallback.qunit.js +33 -38
  434. package/test/sap/ui/core/qunit/CustomThemeFallback_unavoidablySync.qunit.js +119 -0
  435. package/test/sap/ui/core/qunit/EventBus.qunit.js +15 -0
  436. package/test/sap/ui/core/qunit/Lib_terminologies.qunit.js +109 -0
  437. package/test/sap/ui/core/qunit/StashedControlSupport_unavoidablySync.qunit.js +19 -0
  438. package/test/sap/ui/core/qunit/StashedControlSupport_unavoidablySync.view.xml +27 -0
  439. package/test/sap/ui/core/qunit/app/ThemeClassParameters.qunit.js +105 -140
  440. package/test/sap/ui/core/qunit/app/testsuite.app.qunit.js +75 -2
  441. package/test/sap/ui/core/qunit/base/Config.qunit.js +6 -2
  442. package/test/sap/ui/core/qunit/base/Config_bootstrap.qunit.html +4 -1
  443. package/test/sap/ui/core/qunit/base/Config_bootstrap.qunit.js +6 -2
  444. package/test/sap/ui/core/qunit/base/Config_cascade.qunit.js +6 -3
  445. package/test/sap/ui/core/qunit/base/Config_global.qunit.html +5 -2
  446. package/test/sap/ui/core/qunit/base/Config_meta.qunit.html +5 -2
  447. package/test/sap/ui/core/qunit/base/Config_noUrl.qunit.html +5 -2
  448. package/test/sap/ui/core/qunit/base/Config_noUrl.qunit.js +5 -1
  449. package/test/sap/ui/core/qunit/base/Config_url.qunit.html +5 -2
  450. package/test/sap/ui/core/qunit/bootstrap/BootstrapWithNoJQuery-without-jquery-ui-position.qunit.html +2 -1
  451. package/test/sap/ui/core/qunit/bootstrap/BootstrapWithNoJQuery.qunit.html +2 -1
  452. package/test/sap/ui/core/qunit/bootstrap/DebugMode.beforeBootstrap.qunit.js +7 -0
  453. package/test/sap/ui/core/qunit/bootstrap/DebugModeAsync.qunit.html +10 -4
  454. package/test/sap/ui/core/qunit/bootstrap/testsuite.bootstrap.qunit.js +7 -0
  455. package/test/sap/ui/core/qunit/component/Component_keepAlive.qunit.js +9 -0
  456. package/test/sap/ui/core/qunit/gherkin/fixture/testHarnessAmbiguous.html +2 -2
  457. package/test/sap/ui/core/qunit/gherkin/fixture/testHarnessDuplicate.html +2 -2
  458. package/test/sap/ui/core/qunit/gherkin/fixture/testHarnessFailing.html +2 -2
  459. package/test/sap/ui/core/qunit/gherkin/opa5TestHarness.qunit.html +2 -2
  460. package/test/sap/ui/core/qunit/gherkin/qUnitTestHarness.qunit.html +2 -2
  461. package/test/sap/ui/core/qunit/gherkin/testHarnessTests.js +1 -1
  462. package/test/sap/ui/core/qunit/i18n/GenericLocaleData.qunit.js +1 -1
  463. package/test/sap/ui/core/qunit/i18n/LocaleData.qunit.js +15 -15
  464. package/test/sap/ui/core/qunit/i18n/testsuite.i18n.qunit.js +7 -1
  465. package/test/sap/ui/core/qunit/loader/config.qunit.js +14 -6
  466. package/test/sap/ui/core/qunit/model/PropertyBinding.qunit.js +288 -0
  467. package/test/sap/ui/core/qunit/model/controlhelper/TreeBindingProxy.qunit.js +12 -0
  468. package/test/sap/ui/core/qunit/mvc/Controller.qunit.js +7 -2
  469. package/test/sap/ui/core/qunit/odata/v2/ODataModel.integration.qunit.js +225 -40
  470. package/test/sap/ui/core/qunit/odata/v2/ODataPropertyBinding.qunit.js +78 -7
  471. package/test/sap/ui/core/qunit/odata/v4/Context.qunit.js +142 -17
  472. package/test/sap/ui/core/qunit/odata/v4/ODataContextBinding.qunit.js +93 -87
  473. package/test/sap/ui/core/qunit/odata/v4/ODataListBinding.qunit.js +116 -86
  474. package/test/sap/ui/core/qunit/odata/v4/ODataMetaModel.qunit.js +3 -3
  475. package/test/sap/ui/core/qunit/odata/v4/ODataModel.integration.qunit.js +1828 -548
  476. package/test/sap/ui/core/qunit/odata/v4/ODataModel.realOData.qunit.js +1 -1
  477. package/test/sap/ui/core/qunit/odata/v4/ODataParentBinding.qunit.js +1 -1
  478. package/test/sap/ui/core/qunit/odata/v4/ODataPropertyBinding.qunit.js +26 -23
  479. package/test/sap/ui/core/qunit/odata/v4/data/metadata_special_cases.xml +9 -0
  480. package/test/sap/ui/core/qunit/odata/v4/lib/_AggregationCache.qunit.js +251 -113
  481. package/test/sap/ui/core/qunit/odata/v4/lib/_AggregationHelper.qunit.js +50 -0
  482. package/test/sap/ui/core/qunit/odata/v4/lib/_Cache.qunit.js +3 -3
  483. package/test/sap/ui/core/qunit/odata/v4/lib/_Helper.qunit.js +31 -11
  484. package/test/sap/ui/core/qunit/odata/v4/lib/_Parser.qunit.js +8 -2
  485. package/test/sap/ui/core/qunit/odata/v4/lib/_Requestor.qunit.js +46 -31
  486. package/test/sap/ui/core/qunit/odata/v4/lib/_TreeState.qunit.js +144 -45
  487. package/test/sap/ui/core/qunit/odata/v4/lib/_V2Requestor.qunit.js +5 -5
  488. package/test/sap/ui/core/qunit/odata/v4/lib/data/v2/QM_INSP_PLAN_SRV/metadata.xml +3 -3
  489. package/test/sap/ui/core/qunit/odata/v4/lib/data/v2/QM_INSP_PLAN_SRV/metadata_only.xml +3 -3
  490. package/test/sap/ui/core/qunit/opa/autowaiter/_jsAnimationWaiter.js +82 -0
  491. package/test/sap/ui/core/qunit/testdata/libraries/terminologies/simple/i18n/i18n_fr.properties +1 -0
  492. package/test/sap/ui/core/qunit/testdata/libraries/terminologies/simple/i18n/terminologies/oil/i18n_fr.properties +2 -0
  493. package/test/sap/ui/core/qunit/testdata/libraries/terminologies/simple/library-preload.js +2 -2
  494. package/test/sap/ui/core/qunit/testdata/uilib-custom-theme-fallback/themes/sap_hcb/library.css +3 -0
  495. package/test/sap/ui/core/qunit/testsuite.core.framework.qunit.js +19 -1
  496. package/test/sap/ui/core/qunit/testsuites/testsuite.theming.qunit.js +14 -0
  497. package/test/sap/ui/core/qunit/types/NumberFormat.qunit.js +37 -20
  498. package/test/sap/ui/core/qunit/types/NumberFormatCurrencies.qunit.js +21 -0
  499. package/test/sap/ui/core/qunit/types/Types.qunit.js +126 -15
  500. package/test/sap/ui/core/qunit/ui5classes/ManagedObject.qunit.js +58 -4
  501. package/test/sap/ui/core/relnotes/changes-1.122.json +0 -22
  502. package/test/sap/ui/core/relnotes/changes-1.123.json +47 -0
  503. package/test/sap/ui/core/samples/databinding/DataBindingDeclarativeSyntax.js +55 -56
  504. package/test/sap/ui/core/samples/databinding/DatabindingDeclarativeSyntax.html +4 -4
  505. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/firstItem-contextMenu.ref.lnk +1 -1
  506. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/initial.ref.lnk +1 -1
  507. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/lastItem-contextMenu.ref.lnk +1 -1
  508. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/leftDownBtn-contextMenu.ref.lnk +1 -1
  509. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/myButtonSample-contextMenu.ref.lnk +1 -1
  510. package/test/sap/ui/core/visual/images/ContextMenuSupport/windows/1600x1200/chrome/horizon/ltr/cozy/rightDownBtn-contextMenu.ref.lnk +1 -1
  511. package/test/testsuite/js/testfwk.js +47 -64
  512. package/test/sap/ui/core/demokit/sample/MessageManager/BasicMessages/MessagePopover.fragment.xml +0 -13
  513. package/test/sap/ui/core/demokit/sample/MessageManager/BasicMessages/View.view.xml +0 -136
  514. package/test/sap/ui/core/demokit/sample/MessageManager/BasicODataMessages/Controller.controller.js +0 -74
  515. package/test/sap/ui/core/demokit/sample/MessageManager/BasicODataMessages/MessagePopover.fragment.xml +0 -13
  516. package/test/sap/ui/core/demokit/sample/MessageManager/BasicODataMessages/View.view.xml +0 -58
  517. package/test/sap/ui/core/demokit/sample/MessageManager/ODataBackendMessagesComp/ui5.yaml +0 -11
  518. package/test/sap/ui/core/demokit/sample/MessageManager/ODataBackendMessagesComp/webapp/controller/App.controller.js +0 -14
  519. package/test/sap/ui/core/demokit/sample/MessageManager/ODataBackendMessagesComp/webapp/controller/BaseController.js +0 -55
  520. package/test/sap/ui/core/demokit/sample/MessageManager/ODataBackendMessagesComp/webapp/controller/Employee.controller.js +0 -56
  521. package/test/sap/ui/core/demokit/sample/MessageManager/ODataBackendMessagesComp/webapp/fragment/MessagePopover.fragment.xml +0 -13
  522. package/test/sap/ui/core/demokit/sample/MessageManager/ODataBackendMessagesComp/webapp/i18n/i18n.properties +0 -5
  523. package/test/sap/ui/core/demokit/sample/MessageManager/ODataBackendMessagesComp/webapp/index.html +0 -42
  524. package/test/sap/ui/core/demokit/sample/MessageManager/ODataBackendMessagesComp/webapp/view/NotFound.view.xml +0 -11
  525. package/test/sap/ui/core/qunit/app/beforeBootstrap.js +0 -19
  526. package/test/sap/ui/core/qunit/base/i18n/Formatting.qunit.html +0 -24
  527. /package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/BasicODataMessages/localService/metadata.xml +0 -0
  528. /package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/BasicODataMessages/localService/mockdata/Employees.json +0 -0
  529. /package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/BasicODataMessages/localService/response/ODataErrorResponse.json +0 -0
  530. /package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/webapp/localService/metadata.xml +0 -0
  531. /package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/webapp/localService/mockdata/Employees.json +0 -0
  532. /package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/webapp/localService/mockdata/Employees_3.json +0 -0
  533. /package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/webapp/localService/response/ODataErrorResponseTemplate.json +0 -0
  534. /package/test/sap/ui/core/demokit/sample/{MessageManager → Messaging}/ODataBackendMessagesComp/webapp/localService/response/SAP-Message-Header.json +0 -0
@@ -49,7 +49,7 @@ sap.ui.define([
49
49
  "use strict";
50
50
 
51
51
  // system query options for collection responses, but not inside $expand
52
- var rCollection = /[?&]\$(?:count|filter|orderby|search)/,
52
+ var rCollection = /[?&]\$(?:count|filter|orderby|search|skip|top)/,
53
53
  sContext = "sap.ui.model.odata.v4.Context",
54
54
  rCountTrue = /[?&]\$count=true/, // $count=true, but not inside $expand
55
55
  rCountUrl = /\/\$count(?:\?|$)/, // URL for ".../$count?..."
@@ -266,6 +266,20 @@ sap.ui.define([
266
266
  }
267
267
  }
268
268
 
269
+ /**
270
+ * Checks that the given context looks "persisted, not created".
271
+ *
272
+ * @param {object} assert - The QUnit assert object
273
+ * @param {sap.ui.model.odata.v4.Context} oContext - A context
274
+ */
275
+ function checkPersisted(assert, oContext) {
276
+ assert.strictEqual(oContext.created(), undefined, "persisted, not created");
277
+ assert.strictEqual(oContext.getProperty("@$ui5.context.isTransient"), undefined);
278
+ assert.strictEqual(oContext.isTransient(), undefined);
279
+ // Note: due to cloning, undefined values are dropped anyway
280
+ // assert.notOk("@$ui5.context.isTransient" in oContext.getObject());
281
+ }
282
+
269
283
  /**
270
284
  * Checks the selection state of the given context.
271
285
  *
@@ -340,12 +354,8 @@ sap.ui.define([
340
354
  * @returns {Error}
341
355
  * The error object for {@link #expectRequest}
342
356
  */
343
- function createError(oErrorResponse, iHttpStatus, dRetryAfter) {
344
- var oError;
345
-
346
- iHttpStatus = iHttpStatus || 500;
347
-
348
- oError = new Error("Communication error: " + iHttpStatus + " ");
357
+ function createError(oErrorResponse, iHttpStatus = 500, dRetryAfter = false) {
358
+ const oError = new Error("Communication error: " + iHttpStatus + " ");
349
359
  if (oErrorResponse) {
350
360
  oError.error = Object.assign({
351
361
  code : "CODE",
@@ -490,7 +500,7 @@ sap.ui.define([
490
500
  }
491
501
 
492
502
  /**
493
- * Creates a test with the given title and executes viewStart with the given parameters.
503
+ * Creates a test with the given title and invokes viewStart with the given parameters.
494
504
  *
495
505
  * @param {string} sTitle The title of the test case
496
506
  * @param {string} sView The XML snippet of the view
@@ -1159,7 +1169,7 @@ sap.ui.define([
1159
1169
  * @param {boolean} bDropFromCollection If <code>true</code> the context is no longer in
1160
1170
  * the collection
1161
1171
  * @param {function} [fnOnBeforeDestroy]
1162
- * Call back function that is executed once the kept-alive context gets destroyed.
1172
+ * Call back function that is invoked once the kept-alive context gets destroyed.
1163
1173
  * @returns {Promise} A promise that is resolved with the kept-alive context when the
1164
1174
  * view is created and ready
1165
1175
  */
@@ -1722,6 +1732,10 @@ sap.ui.define([
1722
1732
  delete oActualRequest.headers["Accept-Language"];
1723
1733
  delete oActualRequest.headers["Content-Type"];
1724
1734
  if (oExpectedRequest) {
1735
+ if (!oExpectedRequest.headers) {
1736
+ oExpectedRequest.headers = {};
1737
+ delete oActualRequest.headers["sap-cancel-on-close"];
1738
+ }
1725
1739
  oResponse = oExpectedRequest.response;
1726
1740
  if (typeof oResponse === "function") { // invoke "just in time"
1727
1741
  oResponse = oResponse();
@@ -1743,7 +1757,7 @@ sap.ui.define([
1743
1757
  oActualRequest.$ContentID = sContentID;
1744
1758
  }
1745
1759
  assert.deepEqual(oActualRequest, oExpectedRequest,
1746
- sMethod + " " + readableUrl(sUrl));
1760
+ sMethod + " " + readableUrl(sUrl) + " (batchNo: " + iBatchNo + ")");
1747
1761
  } else {
1748
1762
  assert.ok(false, sMethod + " " + readableUrl(sUrl) + " (unexpected)");
1749
1763
  oResponse = {value : []}; // dummy response to avoid further errors
@@ -1989,7 +2003,7 @@ sap.ui.define([
1989
2003
 
1990
2004
  // Ensures that oObject[vProperty] is an array and returns it
1991
2005
  function array(oObject, vProperty) {
1992
- oObject[vProperty] = oObject[vProperty] || [];
2006
+ oObject[vProperty] ??= [];
1993
2007
 
1994
2008
  return oObject[vProperty];
1995
2009
  }
@@ -2068,7 +2082,7 @@ sap.ui.define([
2068
2082
  };
2069
2083
 
2070
2084
  aExpectedEvents.forEach(function (aExpectedDetails) {
2071
- aExpectedDetails[0] = aExpectedDetails[0] || "";
2085
+ aExpectedDetails[0] ??= "";
2072
2086
  if (!aExpectedDetails[0].startsWith(sExpectedEventSourcePrefix)) {
2073
2087
  aExpectedDetails[0] = sExpectedEventSourcePrefix + aExpectedDetails[0];
2074
2088
  }
@@ -2083,8 +2097,11 @@ sap.ui.define([
2083
2097
 
2084
2098
  /**
2085
2099
  * The following code (either {@link #createView} or anything before
2086
- * {@link #waitForChanges}) is expected to report at least the given message. All expected
2087
- * messages should have a different message text.
2100
+ * {@link #waitForChanges}) is expected to report the given message. It is added to the list
2101
+ * of messages that the MessageModel should contain in the end (see
2102
+ * {@link #expectMessages}).
2103
+ *
2104
+ * Note : All expected messages should have a different message text.
2088
2105
  *
2089
2106
  * @param {object} oExpectedMessage The expected message with properties corresponding
2090
2107
  * to the getters of sap.ui.core.message.Message: message and type are required; code,
@@ -2092,8 +2109,6 @@ sap.ui.define([
2092
2109
  * false) are optional; technicalDetails is only compared if given
2093
2110
  * @param {boolean} [bHasMatcher] Whether the expected message has a Sinon.JS matcher
2094
2111
  * @returns {object} The test instance for chaining
2095
- *
2096
- * @see #expectMessages
2097
2112
  */
2098
2113
  expectMessage : function (oExpectedMessage, bHasMatcher) {
2099
2114
  const aTargets = oExpectedMessage.targets || [oExpectedMessage.target || ""];
@@ -2117,9 +2132,12 @@ sap.ui.define([
2117
2132
  },
2118
2133
 
2119
2134
  /**
2120
- * The following code (either {@link #createView} or anything before
2121
- * {@link #waitForChanges}) is expected to report *exactly* the given messages. All expected
2122
- * messages should have a different message text.
2135
+ * The MessageModel is expected to contain <b>exactly</b> the given messages when either
2136
+ * {@link #createView} or {@link #waitForChanges}) have finished. This expectation remains
2137
+ * valid for each subsequent {@link #waitForChanges}), until a new expectation is given.
2138
+ *
2139
+ * Note: The order does not matter, but all expected messages should have a different
2140
+ * message text.
2123
2141
  *
2124
2142
  * @param {object[]} aExpectedMessages The expected messages with properties corresponding
2125
2143
  * to the getters of sap.ui.core.message.Message: message and type are required; code,
@@ -2204,9 +2222,8 @@ sap.ui.define([
2204
2222
  }
2205
2223
  }
2206
2224
  // ensure that these properties are defined (required for deepEqual)
2207
- vRequest.headers = vRequest.headers || {};
2208
- vRequest.method = vRequest.method || "GET";
2209
- vRequest.payload = vRequest.payload || undefined;
2225
+ vRequest.method ??= "GET";
2226
+ vRequest.payload ??= undefined;
2210
2227
  vRequest.responseHeaders = mResponseHeaders || {};
2211
2228
  vRequest.response = vResponse
2212
2229
  // With GET it must be visible that there is no content, with the other
@@ -2704,6 +2721,59 @@ sap.ui.define([
2704
2721
  });
2705
2722
  });
2706
2723
 
2724
+ //*********************************************************************************************
2725
+ // Scenario: PATCH an entity with a key predicate consisting of a single key property of type
2726
+ // Edm.DateTimeOffset. The PATCH failed and a UI5 message is created.
2727
+ // SNOW: CS20240007200281
2728
+ QUnit.test("CS20240007200281: key property is Edm.DateTimeOffset", async function (assert) {
2729
+ const oModel = this.createSpecialCasesModel({autoExpandSelect : true});
2730
+ const sView = `
2731
+ <Table id="table" items="{/Artists(ArtistID='42',IsActiveEntity=true)/_Event}">
2732
+ <Input id="name" value="{Name}"/>
2733
+ </Table>`;
2734
+
2735
+ this.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)/_Event"
2736
+ + "?$select=Name,TimeStamp&$skip=0&$top=100", {
2737
+ value : [
2738
+ {Name : "Taubertal Festival", TimeStamp : "08-08-2024T01:02:03Z"}
2739
+ ]
2740
+ })
2741
+ .expectChange("name", ["Taubertal Festival"]);
2742
+
2743
+ await this.createView(assert, sView, oModel);
2744
+ const aTableRows = this.oView.byId("table").getItems();
2745
+
2746
+ this.expectChange("name", ["Woodstock"])
2747
+ .expectRequest({
2748
+ method : "PATCH",
2749
+ url : "Artists(ArtistID='42',IsActiveEntity=true)"
2750
+ + "/_Event(08-08-2024T01%3A02%3A03Z)",
2751
+ payload : {Name : "Woodstock"}
2752
+ }, createErrorInsideBatch({target : "Name"}))
2753
+ .expectMessages([{
2754
+ code : "CODE",
2755
+ message : "Request intentionally failed",
2756
+ persistent : true,
2757
+ target : "/Artists(ArtistID='42',IsActiveEntity=true)"
2758
+ + "/_Event(08-08-2024T01%3A02%3A03Z)/Name",
2759
+ technical : true,
2760
+ type : "Error"
2761
+ }]);
2762
+
2763
+ this.oLogMock.expects("error")
2764
+ .withArgs("Failed to update path /Artists(ArtistID='42',IsActiveEntity=true)"
2765
+ + "/_Event(08-08-2024T01%3A02%3A03Z)/Name");
2766
+
2767
+ const oInput = aTableRows[0].getCells()[0];
2768
+ // code under test
2769
+ oInput.getBinding("value").setValue("Woodstock");
2770
+
2771
+ await this.waitForChanges(assert);
2772
+
2773
+ await this.checkValueState(assert, oInput, "Error",
2774
+ "Request intentionally failed");
2775
+ });
2776
+
2707
2777
  //*********************************************************************************************
2708
2778
  // Scenario: Minimal test for an absolute ODataPropertyBinding. This scenario is comparable with
2709
2779
  // "FavoriteProduct" in the SalesOrders application.
@@ -3129,7 +3199,7 @@ sap.ui.define([
3129
3199
  // Scenario: Function import.
3130
3200
  // This scenario is similar to the "Favorite product ID" in the SalesOrders application. In the
3131
3201
  // SalesOrders application the binding context is set programmatically. This example directly
3132
- // triggers the function import.
3202
+ // invokes the function import.
3133
3203
  testViewStart("FunctionImport", '\
3134
3204
  <FlexBox binding="{/GetEmployeeByID(EmployeeID=\'2\')}">\
3135
3205
  <Text id="text" text="{Name}"/>\
@@ -3686,7 +3756,7 @@ sap.ui.define([
3686
3756
  });
3687
3757
 
3688
3758
  return Promise.all([
3689
- that.oView.byId("action").getObjectBinding().execute(),
3759
+ that.oView.byId("action").getObjectBinding().invoke(),
3690
3760
  that.waitForChanges(assert)
3691
3761
  ]);
3692
3762
  }).then(function (aResults) {
@@ -3715,7 +3785,7 @@ sap.ui.define([
3715
3785
  });
3716
3786
 
3717
3787
  //*********************************************************************************************
3718
- // Scenario: Immediately after execute the parameter is changed again. See that the request uses
3788
+ // Scenario: Immediately after invoke the parameter is changed again. See that the request uses
3719
3789
  // the old value. Even refresh must still use it.
3720
3790
  // BCP: 2070180785
3721
3791
  // TODO What about changing the context for the binding parameter?
@@ -3730,7 +3800,7 @@ sap.ui.define([
3730
3800
 
3731
3801
  oBinding = that.oModel.bindContext("/GetEmployeeByID(...)");
3732
3802
  oBinding.setParameter("EmployeeID", "1");
3733
- oPromise = oBinding.execute();
3803
+ oPromise = oBinding.invoke();
3734
3804
  oBinding.setParameter("EmployeeID", "2");
3735
3805
 
3736
3806
  return Promise.all([oPromise, that.waitForChanges(assert)]);
@@ -3744,7 +3814,7 @@ sap.ui.define([
3744
3814
  that.expectRequest("GetEmployeeByID(EmployeeID='2')", {ID : "2"});
3745
3815
 
3746
3816
  return Promise.all([
3747
- oBinding.execute(),
3817
+ oBinding.invoke(),
3748
3818
  that.waitForChanges(assert)
3749
3819
  ]);
3750
3820
  });
@@ -3921,7 +3991,7 @@ sap.ui.define([
3921
3991
  });
3922
3992
 
3923
3993
  return Promise.all([
3924
- that.oView.byId("action").getObjectBinding().execute(),
3994
+ that.oView.byId("action").getObjectBinding().invoke(),
3925
3995
  that.waitForChanges(assert)
3926
3996
  ]);
3927
3997
  }).then(function (aResults) {
@@ -5152,6 +5222,7 @@ sap.ui.define([
5152
5222
  //*********************************************************************************************
5153
5223
  // Scenario: Failure to read from an ODataContextBinding returning a bound message
5154
5224
  // BCP: 2070436327: the data state is updated if unbindProperty is called
5225
+ // "sap-cancel-on-close" header for $direct GET request (JIRA: CPOUI5ODATAV4-2506)
5155
5226
  QUnit.test("ODCB: read failure & message", function (assert) {
5156
5227
  var oError = createError({
5157
5228
  message : "Could not read",
@@ -5170,7 +5241,10 @@ sap.ui.define([
5170
5241
  this.oLogMock.expects("error")
5171
5242
  .withExactArgs("Failed to read path /EMPLOYEES('42')/Name", sinon.match(oError.message),
5172
5243
  sODPrB);
5173
- this.expectRequest("EMPLOYEES('42')", oError)
5244
+ this.expectRequest({
5245
+ headers : {"sap-cancel-on-close" : "true"},
5246
+ url : "EMPLOYEES('42')"
5247
+ }, oError)
5174
5248
  .expectMessages([{
5175
5249
  code : "CODE",
5176
5250
  message : "Could not read",
@@ -5701,7 +5775,7 @@ sap.ui.define([
5701
5775
  });
5702
5776
 
5703
5777
  return Promise.all([
5704
- that.oView.byId("action").getObjectBinding().execute(),
5778
+ that.oView.byId("action").getObjectBinding().invoke(),
5705
5779
  that.waitForChanges(assert)
5706
5780
  ]);
5707
5781
  }).then(function (aResults) {
@@ -6310,7 +6384,7 @@ sap.ui.define([
6310
6384
  that.oView.byId("form").getObjectBinding()
6311
6385
  .setParameter("TeamID", "TEAM_01")
6312
6386
  .setParameter("Budget", "1234.1234")
6313
- .execute(),
6387
+ .invoke(),
6314
6388
  that.waitForChanges(assert)
6315
6389
  ]);
6316
6390
  }).then(function () {
@@ -6426,7 +6500,7 @@ sap.ui.define([
6426
6500
  }
6427
6501
  }); // response does not matter here
6428
6502
 
6429
- oOperationBinding.execute();
6503
+ oOperationBinding.invoke();
6430
6504
 
6431
6505
  return that.waitForChanges(assert);
6432
6506
  }).then(function () {
@@ -6532,7 +6606,7 @@ sap.ui.define([
6532
6606
  }, {/* response does not matter here */});
6533
6607
 
6534
6608
  // code under test
6535
- oOperation.execute();
6609
+ oOperation.invoke();
6536
6610
 
6537
6611
  return that.waitForChanges(assert);
6538
6612
  }).then(function () {
@@ -6544,7 +6618,7 @@ sap.ui.define([
6544
6618
  });
6545
6619
 
6546
6620
  that.oLogMock.expects("error")
6547
- .withExactArgs("Failed to execute /ChangeTeamBudgetByID(...)",
6621
+ .withExactArgs("Failed to invoke /ChangeTeamBudgetByID(...)",
6548
6622
  sinon.match(oError.message), sODCB);
6549
6623
  that.expectRequest({
6550
6624
  method : "POST",
@@ -6568,7 +6642,7 @@ sap.ui.define([
6568
6642
  .expectChange("budget", "-42");
6569
6643
 
6570
6644
  return Promise.all([
6571
- oOperation.setParameter("Budget", "-42").execute()
6645
+ oOperation.setParameter("Budget", "-42").invoke()
6572
6646
  .then(mustFail(assert), function (oError0) {
6573
6647
  assert.strictEqual(oError0, oError);
6574
6648
  }),
@@ -6786,7 +6860,7 @@ sap.ui.define([
6786
6860
  }, {/* response does not matter here */});
6787
6861
 
6788
6862
  // code under test
6789
- return Promise.all([oOperation.execute(), that.waitForChanges(assert)]);
6863
+ return Promise.all([oOperation.invoke(), that.waitForChanges(assert)]);
6790
6864
  });
6791
6865
  });
6792
6866
 
@@ -6830,7 +6904,7 @@ sap.ui.define([
6830
6904
 
6831
6905
  return Promise.all([
6832
6906
  // code under test
6833
- oOperation.execute(),
6907
+ oOperation.invoke(),
6834
6908
  that.waitForChanges(assert)
6835
6909
  ]);
6836
6910
  }).then(function () {
@@ -7100,7 +7174,7 @@ sap.ui.define([
7100
7174
  // * See that the count decreases
7101
7175
  // The delete is used to change the count (to see that it is still updated)
7102
7176
  //
7103
- // Call ODLB#sort with the same Sorter as before. This should not trigger a request.
7177
+ // Call ODLB#sort with the same Sorter as before. This should not invoke a request.
7104
7178
  // JIRA: CPOUI5ODATAV4-942
7105
7179
  QUnit.test("ODLB: $count and sort()", function (assert) {
7106
7180
  var oTable,
@@ -7383,7 +7457,7 @@ sap.ui.define([
7383
7457
 
7384
7458
  //*********************************************************************************************
7385
7459
  // Scenario: A relative list binding's context is changed. Additionally a refresh (via
7386
- // requestSideEffects) is triggered after the binding has recreated its cache, but before the
7460
+ // requestSideEffects) is invoked after the binding has recreated its cache, but before the
7387
7461
  // dependent property bindings have been destroyed. In the incident, the list table contains
7388
7462
  // the items and the detail table the schedules (with 1:n, which we don't have here).
7389
7463
  // BCP: 2080123400
@@ -7723,7 +7797,7 @@ sap.ui.define([
7723
7797
  oBinding.suspend();
7724
7798
  oBinding.refresh();
7725
7799
 
7726
- // Do not immediately resume to see that no requests are triggered by refresh
7800
+ // Do not immediately resume to see that no requests are invoked by refresh
7727
7801
  return resolveLater();
7728
7802
  }).then(function () {
7729
7803
  that.expectEvents(assert, "sap.ui.model.odata.v4.OData", [
@@ -8111,6 +8185,8 @@ sap.ui.define([
8111
8185
  //
8112
8186
  // Tell the model to ignore the ETag, but no If-Match:* must be sent unless an ETag was present
8113
8187
  // JIRA: CPOUI5ODATAV4-1894
8188
+ //
8189
+ // No "sap-cancel-on-close" header in PATCH request (JIRA: CPOUI5ODATAV4-2506)
8114
8190
  ["$auto", "$direct"].forEach(function (sGroupId) {
8115
8191
  [false, true].forEach(function (bETag) {
8116
8192
  var sTitle = "Modify a property, server responds with 204 (No Content), group = " + sGroupId
@@ -11734,6 +11810,8 @@ sap.ui.define([
11734
11810
 
11735
11811
  //*********************************************************************************************
11736
11812
  // Scenario: Failure when creating a sales order line item. Observe the message.
11813
+ //
11814
+ // No "sap-cancel-on-close" header in POST request (JIRA: CPOUI5ODATAV4-2506)
11737
11815
  QUnit.test("Create error", function (assert) {
11738
11816
  var oModel = this.createSalesOrdersModel({autoExpandSelect : true, groupId : "$direct"}),
11739
11817
  oTable,
@@ -11764,6 +11842,7 @@ sap.ui.define([
11764
11842
  + "will be repeated automatically", sinon.match(oError.message), sODLB);
11765
11843
  that.expectRequest({
11766
11844
  method : "POST",
11845
+ headers : {/*NO "sap-cancel-on-close"*/},
11767
11846
  url : "SalesOrderList('42')/SO_2_SOITEM",
11768
11847
  payload : {}
11769
11848
  }, oError)
@@ -12340,16 +12419,16 @@ sap.ui.define([
12340
12419
  });
12341
12420
 
12342
12421
  //*********************************************************************************************
12343
- // Scenario: Execute a bound action while an update request for the entity is not yet
12422
+ // Scenario: Invoke a bound action while an update request for the entity is not yet
12344
12423
  // resolved. Determine the ETag as late as possible.
12345
12424
  // JIRA: CPOUI5UISERVICESV3-1450
12346
12425
  //
12347
12426
  // Do not update binding parameter when both key predicates are missing.
12348
12427
  // JIRA: CPOUI5ODATAV4-1683
12349
- QUnit.test("Lazy determination of ETag while ODataContextBinding#execute", function (assert) {
12428
+ QUnit.test("Lazy determination of ETag while ODataContextBinding#invoke", function (assert) {
12350
12429
  var sAction = "com.sap.gateway.default.iwbep.tea_busi.v0001.AcChangeTeamOfEmployee",
12351
12430
  oBinding,
12352
- oExecutePromise,
12431
+ oInvokePromise,
12353
12432
  oModel = this.createTeaBusiModel({updateGroupId : "update"}),
12354
12433
  fnRespond,
12355
12434
  oSubmitBatchPromise,
@@ -12386,7 +12465,7 @@ sap.ui.define([
12386
12465
  Name : "Jonathan Müller"
12387
12466
  });
12388
12467
  }))
12389
- .expectChange("name", "Jonathan Mueller"); // triggered by setValue
12468
+ .expectChange("name", "Jonathan Mueller"); // invoked by setValue
12390
12469
 
12391
12470
  oBinding.setValue("Jonathan Mueller");
12392
12471
 
@@ -12394,10 +12473,10 @@ sap.ui.define([
12394
12473
 
12395
12474
  return that.waitForChanges(assert);
12396
12475
  }).then(function () {
12397
- oExecutePromise = that.oView.byId("action").getObjectBinding()
12398
- .setParameter("TeamID", "42").execute("update");
12476
+ oInvokePromise = that.oView.byId("action").getObjectBinding()
12477
+ .setParameter("TeamID", "42").invoke("update");
12399
12478
 
12400
- that.expectChange("name", "Jonathan Müller"); // triggered by PATCH response
12479
+ that.expectChange("name", "Jonathan Müller"); // invoked by PATCH response
12401
12480
  fnRespond();
12402
12481
 
12403
12482
  return Promise.all([
@@ -12419,7 +12498,7 @@ sap.ui.define([
12419
12498
 
12420
12499
  return Promise.all([
12421
12500
  that.oModel.submitBatch("update"),
12422
- oExecutePromise.then(function (oReturnValueContext) {
12501
+ oInvokePromise.then(function (oReturnValueContext) {
12423
12502
  assert.strictEqual(oReturnValueContext, undefined,
12424
12503
  "no R.V.C. w/o key predicate");
12425
12504
  }),
@@ -12429,13 +12508,13 @@ sap.ui.define([
12429
12508
  });
12430
12509
 
12431
12510
  //*********************************************************************************************
12432
- // Scenario: Execute a bound action a 2nd time while the 1st POST is still "in flight"
12511
+ // Scenario: Invoke a bound action a 2nd time while the 1st POST is still "in flight"
12433
12512
  // BCP: 2380023421
12434
- QUnit.test("Lazy determination of ETag by ODataContextBinding#execute", function (assert) {
12513
+ QUnit.test("Lazy determination of ETag by ODataContextBinding#invoke", function (assert) {
12435
12514
  var sAction = "com.sap.gateway.default.iwbep.tea_busi.v0001.AcChangeTeamOfEmployee",
12436
12515
  oContext,
12437
- oExecutePromise1,
12438
- oExecutePromise2,
12516
+ oInvokePromise1,
12517
+ oInvokePromise2,
12439
12518
  oModel = this.createTeaBusiModel({autoExpandSelect : true}),
12440
12519
  fnRespond,
12441
12520
  sView = '\
@@ -12471,19 +12550,19 @@ sap.ui.define([
12471
12550
  });
12472
12551
  }));
12473
12552
 
12474
- oExecutePromise1 = oModel.bindContext(sAction + "(...)", oContext)
12553
+ oInvokePromise1 = oModel.bindContext(sAction + "(...)", oContext)
12475
12554
  .setParameter("TeamID", "42")
12476
- .execute();
12555
+ .invoke();
12477
12556
 
12478
- return that.waitForChanges(assert, "1st #execute");
12557
+ return that.waitForChanges(assert, "1st #invoke");
12479
12558
  }).then(function () {
12480
12559
  // expect no 2nd POST yet!
12481
12560
 
12482
- oExecutePromise2 = oModel.bindContext(sAction + "(...)", oContext)
12561
+ oInvokePromise2 = oModel.bindContext(sAction + "(...)", oContext)
12483
12562
  .setParameter("TeamID", "23")
12484
- .execute();
12563
+ .invoke();
12485
12564
 
12486
- return that.waitForChanges(assert, "2nd #execute");
12565
+ return that.waitForChanges(assert, "2nd #invoke");
12487
12566
  }).then(function () {
12488
12567
  that.expectChange("name", "Jonathan Smith junior")
12489
12568
  .expectChange("teamId", "42")
@@ -12504,11 +12583,11 @@ sap.ui.define([
12504
12583
  fnRespond();
12505
12584
 
12506
12585
  return Promise.all([
12507
- oExecutePromise1,
12508
- oExecutePromise2.then(function () {
12586
+ oInvokePromise1,
12587
+ oInvokePromise2.then(function () {
12509
12588
  assert.strictEqual(oContext.getProperty("@odata.etag"), "ETag2");
12510
12589
  }),
12511
- that.waitForChanges(assert, "1st response triggers 2nd request")
12590
+ that.waitForChanges(assert, "1st response invokes 2nd request")
12512
12591
  ]);
12513
12592
  });
12514
12593
  });
@@ -13462,6 +13541,7 @@ sap.ui.define([
13462
13541
  // Scenario: bound action (success and failure)
13463
13542
  // JIRA: CPOUI5ODATAV4-29 (bound action parameter and error with message target)
13464
13543
  // JIRA: CPOUI5ODATAV4-132 (bind property of binding parameter relative to $Parameter)
13544
+ // No "sap-cancel-on-close" header in POST request (JIRA: CPOUI5ODATAV4-2506)
13465
13545
  QUnit.test("Bound action", function (assert) {
13466
13546
  var oModel = this.createTeaBusiModel({autoExpandSelect : true, groupId : "$direct"}),
13467
13547
  sView = '\
@@ -13516,14 +13596,14 @@ sap.ui.define([
13516
13596
  }).then(function () {
13517
13597
  that.expectRequest({
13518
13598
  method : "POST",
13519
- headers : {"If-Match" : "ETag"},
13599
+ headers : {"If-Match" : "ETag"/*, NO "sap-cancel-on-close"*/},
13520
13600
  url : sUrl,
13521
13601
  payload : {TeamID : "42"}
13522
13602
  }, {TEAM_ID : "42"})
13523
13603
  .expectChange("teamId", "42");
13524
13604
 
13525
13605
  return Promise.all([
13526
- that.oView.byId("action").getObjectBinding().execute()
13606
+ that.oView.byId("action").getObjectBinding().invoke()
13527
13607
  .then(function (oReturnValueContext) {
13528
13608
  assert.strictEqual(oReturnValueContext, undefined,
13529
13609
  "no R.V.C. w/o key predicate");
@@ -13548,14 +13628,14 @@ sap.ui.define([
13548
13628
  }]
13549
13629
  });
13550
13630
 
13551
- that.oLogMock.expects("error").withExactArgs("Failed to execute /" + sUrl + "(...)",
13631
+ that.oLogMock.expects("error").withExactArgs("Failed to invoke /" + sUrl + "(...)",
13552
13632
  sinon.match(oError.message), sODCB);
13553
13633
  that.oLogMock.expects("error").withExactArgs(//TODO: prevent log -> CPOUI5ODATAV4-127
13554
13634
  "Failed to read path /" + sUrl + "(...)/TEAM_ID", sinon.match(oError.message),
13555
13635
  sODPrB);
13556
13636
  that.expectRequest({
13557
13637
  method : "POST",
13558
- headers : {"If-Match" : "ETag"},
13638
+ headers : {"If-Match" : "ETag"/*, NO "sap-cancel-on-close"*/},
13559
13639
  url : sUrl,
13560
13640
  payload : {TeamID : ""}
13561
13641
  }, oError) // simulates failure
@@ -13588,7 +13668,7 @@ sap.ui.define([
13588
13668
  .expectChange("teamId", null); // reset to initial state
13589
13669
 
13590
13670
  return Promise.all([
13591
- that.oView.byId("action").getObjectBinding().setParameter("TeamID", "").execute()
13671
+ that.oView.byId("action").getObjectBinding().setParameter("TeamID", "").invoke()
13592
13672
  .then(mustFail(assert), function (oError0) {
13593
13673
  assert.strictEqual(oError0, oError);
13594
13674
  }),
@@ -13642,7 +13722,7 @@ sap.ui.define([
13642
13722
 
13643
13723
  return Promise.all([
13644
13724
  // code under test
13645
- that.oModel.bindContext("special.cases.GetDefaults(...)", oHeaderContext).execute(),
13725
+ that.oModel.bindContext("special.cases.GetDefaults(...)", oHeaderContext).invoke(),
13646
13726
  that.waitForChanges(assert)
13647
13727
  ]);
13648
13728
  }).then(function (aResults) {
@@ -13685,7 +13765,7 @@ sap.ui.define([
13685
13765
  .setParameter("Name", oDefaults.getObject("Name"));
13686
13766
 
13687
13767
  return Promise.all([
13688
- oAction.execute(),
13768
+ oAction.invoke(),
13689
13769
  that.waitForChanges(assert)
13690
13770
  ]);
13691
13771
  }).then(function (aPromiseResults) {
@@ -13846,7 +13926,7 @@ sap.ui.define([
13846
13926
 
13847
13927
  return Promise.all([
13848
13928
  // code under test
13849
- oAction.execute().then(function (oResult) {
13929
+ oAction.invoke().then(function (oResult) {
13850
13930
  assert.strictEqual(oResult, undefined,
13851
13931
  "no R.V.C. because EMPLOYEE_2_TEAM is missing");
13852
13932
  }),
@@ -13857,14 +13937,14 @@ sap.ui.define([
13857
13937
  });
13858
13938
 
13859
13939
  //*********************************************************************************************
13860
- // Scenario: Execute a bound action for an entity in a list binding and afterwards call refresh
13940
+ // Scenario: Invoke a bound action for an entity in a list binding and afterwards call refresh
13861
13941
  // with bAllowRemoval=true for the context the entity is pointing to. If the entity is gone from
13862
13942
  // the list binding no error should happen because of the just deleted context.
13863
13943
  // TODO Test with a created binding parameter, too. This failed in an OPA test previously.
13864
13944
  QUnit.test("Bound action with context refresh which removes the context", function (assert) {
13865
13945
  var oAction,
13866
13946
  oContext,
13867
- oExecutionPromise,
13947
+ oInvocationPromise,
13868
13948
  oModel = this.createTeaBusiModel({autoExpandSelect : true}),
13869
13949
  sView = '\
13870
13950
  <Table id="table"\
@@ -13906,11 +13986,11 @@ sap.ui.define([
13906
13986
  + ".AcChangeTeamOfEmployee(...)", oContext);
13907
13987
 
13908
13988
  // code under test
13909
- oExecutionPromise = oAction.setParameter("TeamID", "42").execute();
13989
+ oInvocationPromise = oAction.setParameter("TeamID", "42").invoke();
13910
13990
 
13911
13991
  return Promise.all([
13912
13992
  oContext.requestRefresh(undefined, true),
13913
- oExecutionPromise.then(function (oReturnValueContext) {
13993
+ oInvocationPromise.then(function (oReturnValueContext) {
13914
13994
  assert.strictEqual(oReturnValueContext, undefined,
13915
13995
  "no R.V.C. w/o key predicate");
13916
13996
  }),
@@ -13962,7 +14042,7 @@ sap.ui.define([
13962
14042
  // code under test
13963
14043
  that.oView.byId("action").getObjectBinding()
13964
14044
  .setParameter("Message", "The quick brown fox jumps over the lazy dog")
13965
- .execute(undefined, true), // CPOUI5ODATAV4-869
14045
+ .invoke(undefined, true), // CPOUI5ODATAV4-869
13966
14046
  that.waitForChanges(assert)
13967
14047
  ]);
13968
14048
  });
@@ -13993,7 +14073,7 @@ sap.ui.define([
13993
14073
  // code under test
13994
14074
  that.oView.byId("function").getObjectBinding()
13995
14075
  .setParameter("EmployeeID", "1")
13996
- .execute(),
14076
+ .invoke(),
13997
14077
  that.waitForChanges(assert)
13998
14078
  ]);
13999
14079
  });
@@ -14084,7 +14164,7 @@ sap.ui.define([
14084
14164
  // i.e. it changes the initially aggregated query options. Note: It is also possible to remove
14085
14165
  // a filter which must lead to removal of the $filter option.
14086
14166
  //
14087
- // Call ODLB#filter with the same Filter as before. this should not trigger a request.
14167
+ // Call ODLB#filter with the same Filter as before. this should not invoke a request.
14088
14168
  // CPOUI5ODATAV4-942
14089
14169
  QUnit.test("Absolute ODLB with auto-$expand/$select: filter via API", function (assert) {
14090
14170
  var oModel = this.createTeaBusiModel({autoExpandSelect : true}),
@@ -15132,46 +15212,47 @@ sap.ui.define([
15132
15212
  //
15133
15213
  // JIRA: CPOUI5ODATAV4-1628
15134
15214
  QUnit.test("CPOUI5ODATAV4-1628: re-read Edm.Stream URL & readLink", function (assert) {
15135
- var oContext,
15215
+ var sArtist = "Artists(ArtistID='42',IsActiveEntity=true)",
15216
+ oContext,
15136
15217
  oModel = this.createSpecialCasesModel({autoExpandSelect : true}),
15137
- sView = '\
15138
- <FlexBox id="form" binding="{/Artists(ArtistID=\'42\')}">\
15139
- <Text id="picture" text="{Picture}"/>\
15140
- <Text id="link" text="{= %{Picture@odata.mediaReadLink} }"/>\
15141
- </FlexBox>',
15218
+ sView = `
15219
+ <FlexBox id="form" binding="{/${sArtist}}">
15220
+ <Text id="picture" text="{Picture}"/>
15221
+ <Text id="link" text="{= %{Picture@odata.mediaReadLink} }"/>
15222
+ </FlexBox>`,
15142
15223
  sPrefix = "/special/cases/",
15143
15224
  that = this;
15144
15225
 
15145
- this.expectRequest("Artists(ArtistID='42')"
15146
- + "?$select=ArtistID,IsActiveEntity,Picture", {
15147
- ID : "42",
15226
+ this.expectRequest(sArtist + "?$select=ArtistID,IsActiveEntity,Picture", {
15227
+ ArtistID : "42",
15228
+ IsActiveEntity : true,
15148
15229
  // Picture (Edm.Stream) missing here
15149
- "Picture@odata.mediaReadLink" : "Artists(ArtistID='42')/Picture"
15230
+ "Picture@odata.mediaReadLink" : sArtist + "/Picture"
15150
15231
  })
15151
- .expectChange("picture", sPrefix + "Artists(ArtistID='42')/Picture")
15152
- .expectChange("link", sPrefix + "Artists(ArtistID='42')/Picture")
15232
+ .expectChange("picture", sPrefix + sArtist + "/Picture")
15233
+ .expectChange("link", sPrefix + sArtist + "/Picture")
15153
15234
  .expectEvents(assert, "sap.ui.model.odata.v4.OData", [
15154
- ["ContextBinding: /Artists(ArtistID='42')", "change", {reason : "change"}],
15155
- ["ContextBinding: /Artists(ArtistID='42')", "dataRequested", undefined],
15156
- ["ContextBinding: /Artists(ArtistID='42')", "dataReceived", {data : {}}],
15157
- ["PropertyBinding: /Artists(ArtistID='42')|Picture", "change", {reason : "change"}],
15158
- ["PropertyBinding: /Artists(ArtistID='42')"
15159
- + "|Picture@odata.mediaReadLink", "change", {reason : "change"}]
15235
+ ["ContextBinding: /" + sArtist, "change", {reason : "change"}],
15236
+ ["ContextBinding: /" + sArtist, "dataRequested", undefined],
15237
+ ["ContextBinding: /" + sArtist, "dataReceived", {data : {}}],
15238
+ ["PropertyBinding: /" + sArtist + "|Picture", "change", {reason : "change"}],
15239
+ ["PropertyBinding: /" + sArtist + "|Picture@odata.mediaReadLink", "change",
15240
+ {reason : "change"}]
15160
15241
  ]);
15161
15242
 
15162
15243
  return this.createView(assert, sView, oModel).then(function () {
15163
15244
  oContext = that.oView.byId("form").getBindingContext();
15164
15245
 
15165
- that.expectRequest("Artists(ArtistID='42')?$select=Picture", {
15166
- ID : "42",
15246
+ that.expectRequest(sArtist + "?$select=Picture", {
15247
+ ArtistID : "42",
15248
+ IsActiveEntity : true,
15167
15249
  // Picture (Edm.Stream) missing here
15168
- "Picture@odata.mediaReadLink" : "Artists(ArtistID='42')/Picture"
15250
+ "Picture@odata.mediaReadLink" : sArtist + "/Picture"
15169
15251
  })
15170
- .expectChange("picture", sPrefix + "Artists(ArtistID='42')/Picture")
15252
+ .expectChange("picture", sPrefix + sArtist + "/Picture")
15171
15253
  .expectEvents(assert, "sap.ui.model.odata.v4.OData", [
15172
- ["PropertyBinding: /Artists(ArtistID='42')|Picture",
15173
- "change", {reason : "change"}]
15174
- ]);
15254
+ ["PropertyBinding: /" + sArtist + "|Picture", "change", {reason : "change"}]
15255
+ ]);
15175
15256
 
15176
15257
  return Promise.all([
15177
15258
  // code under test
@@ -15179,17 +15260,17 @@ sap.ui.define([
15179
15260
  that.waitForChanges(assert, "(1) unchanged URL via @odata.mediaReadLink annotation")
15180
15261
  ]);
15181
15262
  }).then(function () {
15182
- that.expectRequest("Artists(ArtistID='42')?$select=Picture", {
15183
- ID : "42"
15263
+ that.expectRequest(sArtist + "?$select=Picture", {
15264
+ ArtistID : "42",
15265
+ IsActiveEntity : true
15184
15266
  // Picture (Edm.Stream) missing here
15185
15267
  })
15186
- .expectChange("picture", sPrefix + "Artists(ArtistID='42')/Picture")
15268
+ .expectChange("picture", sPrefix + sArtist + "/Picture")
15187
15269
  .expectChange("link", undefined) // no more Picture@odata.mediaReadlink
15188
15270
  .expectEvents(assert, "sap.ui.model.odata.v4.OData", [
15189
- ["PropertyBinding: /Artists(ArtistID='42')|Picture@odata.mediaReadLink",
15190
- "change", {reason : "change"}],
15191
- ["PropertyBinding: /Artists(ArtistID='42')|Picture",
15192
- "change", {reason : "change"}]
15271
+ ["PropertyBinding: /" + sArtist + "|Picture@odata.mediaReadLink", "change",
15272
+ {reason : "change"}],
15273
+ ["PropertyBinding: /" + sArtist + "|Picture", "change", {reason : "change"}]
15193
15274
  ]);
15194
15275
 
15195
15276
  return Promise.all([
@@ -15198,14 +15279,14 @@ sap.ui.define([
15198
15279
  that.waitForChanges(assert, "(2) no URL in response (calculated by model)")
15199
15280
  ]);
15200
15281
  }).then(function () {
15201
- that.expectRequest("Artists(ArtistID='42')?$select=Picture", {
15202
- ID : "42"
15282
+ that.expectRequest(sArtist + "?$select=Picture", {
15283
+ ArtistID : "42",
15284
+ IsActiveEntity : true
15203
15285
  // Picture (Edm.Stream) missing here
15204
15286
  })
15205
- .expectChange("picture", sPrefix + "Artists(ArtistID='42')/Picture")
15287
+ .expectChange("picture", sPrefix + sArtist + "/Picture")
15206
15288
  .expectEvents(assert, "sap.ui.model.odata.v4.OData", [
15207
- ["PropertyBinding: /Artists(ArtistID='42')|Picture",
15208
- "change", {reason : "change"}]
15289
+ ["PropertyBinding: /" + sArtist + "|Picture", "change", {reason : "change"}]
15209
15290
  ]);
15210
15291
 
15211
15292
  return Promise.all([
@@ -15214,18 +15295,18 @@ sap.ui.define([
15214
15295
  that.waitForChanges(assert, "(3) again, no URL in response (calculated by model)")
15215
15296
  ]);
15216
15297
  }).then(function () {
15217
- that.expectRequest("Artists(ArtistID='42')?$select=Picture", {
15218
- ID : "42",
15298
+ that.expectRequest(sArtist + "?$select=Picture", {
15299
+ ArtistID : "42",
15300
+ IsActiveEntity : true,
15219
15301
  // Picture (Edm.Stream) missing here
15220
- "Picture@odata.mediaReadLink" : "Artists(ArtistID='42')/Picture"
15302
+ "Picture@odata.mediaReadLink" : sArtist + "/Picture"
15221
15303
  })
15222
- .expectChange("picture", sPrefix + "Artists(ArtistID='42')/Picture")
15223
- .expectChange("link", sPrefix + "Artists(ArtistID='42')/Picture")
15304
+ .expectChange("picture", sPrefix + sArtist + "/Picture")
15305
+ .expectChange("link", sPrefix + sArtist + "/Picture")
15224
15306
  .expectEvents(assert, "sap.ui.model.odata.v4.OData", [
15225
- ["PropertyBinding: /Artists(ArtistID='42')|Picture@odata.mediaReadLink",
15226
- "change", {reason : "change"}],
15227
- ["PropertyBinding: /Artists(ArtistID='42')|Picture",
15228
- "change", {reason : "change"}]
15307
+ ["PropertyBinding: /" + sArtist + "|Picture@odata.mediaReadLink", "change",
15308
+ {reason : "change"}],
15309
+ ["PropertyBinding: /" + sArtist + "|Picture", "change", {reason : "change"}]
15229
15310
  ]);
15230
15311
 
15231
15312
  return Promise.all([
@@ -15234,18 +15315,17 @@ sap.ui.define([
15234
15315
  that.waitForChanges(assert, "(4) back to URL via @odata.mediaReadLink")
15235
15316
  ]);
15236
15317
  }).then(function () {
15237
- that.expectRequest("Artists(ArtistID='42')?$select=Picture", {
15318
+ that.expectRequest(sArtist + "?$select=Picture", {
15238
15319
  ID : "42",
15239
15320
  // Picture (Edm.Stream) missing here
15240
- "Picture@odata.mediaReadLink" : "Artists(ArtistID='42')/PictureHighRes"
15321
+ "Picture@odata.mediaReadLink" : sArtist + "/PictureHighRes"
15241
15322
  })
15242
- .expectChange("picture", sPrefix + "Artists(ArtistID='42')/PictureHighRes")
15243
- .expectChange("link", sPrefix + "Artists(ArtistID='42')/PictureHighRes")
15323
+ .expectChange("picture", sPrefix + sArtist + "/PictureHighRes")
15324
+ .expectChange("link", sPrefix + sArtist + "/PictureHighRes")
15244
15325
  .expectEvents(assert, "sap.ui.model.odata.v4.OData", [
15245
- ["PropertyBinding: /Artists(ArtistID='42')|Picture@odata.mediaReadLink",
15246
- "change", {reason : "change"}],
15247
- ["PropertyBinding: /Artists(ArtistID='42')|Picture",
15248
- "change", {reason : "change"}]
15326
+ ["PropertyBinding: /" + sArtist + "|Picture@odata.mediaReadLink", "change",
15327
+ {reason : "change"}],
15328
+ ["PropertyBinding: /" + sArtist + "|Picture", "change", {reason : "change"}]
15249
15329
  ]);
15250
15330
 
15251
15331
  return Promise.all([
@@ -15255,6 +15335,79 @@ sap.ui.define([
15255
15335
  ]);
15256
15336
  });
15257
15337
  });
15338
+
15339
+ //*********************************************************************************************
15340
+ // Scenario: We simulate parts of a file upload here. Initially, the Edm.Stream property is
15341
+ // missing from the response (of course) and a late property request is sent leading to
15342
+ // "Picture@$ui5.noData : true" being set. File upload happens outside the model and only a file
15343
+ // name would be PATCHed, this is omitted here. Removal of the file requires the model to PATCH
15344
+ // a null value, which ruins the URL. Thus the property is reset to undefined on the client side
15345
+ // only. This must not prevent a side effect from setting "Picture@$ui5.noData : true" again!
15346
+ // Thus upload and removal can be repeated (endlessly) while a URL is implicitly available for
15347
+ // up- and download at all times.
15348
+ // SNOW: DINC0088146
15349
+ QUnit.test("DINC0088146", async function (assert) {
15350
+ const oModel = this.createSpecialCasesModel({autoExpandSelect : true});
15351
+ const sView = `
15352
+ <Table id="list" items="{/Artists}">
15353
+ <Text id="id" text="{ArtistID}"/>
15354
+ </Table>
15355
+ <FlexBox id="detail">
15356
+ <Text id="link" text="{Picture}"/>
15357
+ </FlexBox>`;
15358
+ const sLink = "/special/cases/Artists(ArtistID='42',IsActiveEntity=true)/Picture";
15359
+
15360
+ this.expectRequest("Artists?$select=ArtistID,IsActiveEntity&$skip=0&$top=100", {
15361
+ value : [{
15362
+ ArtistID : "42",
15363
+ IsActiveEntity : true
15364
+ }]
15365
+ })
15366
+ .expectChange("link");
15367
+
15368
+ await this.createView(assert, sView, oModel);
15369
+
15370
+ this.expectRequest("Artists(ArtistID='42',IsActiveEntity=true)?$select=Picture", {
15371
+ ArtistID : "42",
15372
+ // Picture (Edm.Stream) missing here
15373
+ "Picture@odata.mediaContentType" : null
15374
+ })
15375
+ .expectChange("link", sLink);
15376
+
15377
+ const oContext = this.oView.byId("list").getItems()[0].getBindingContext();
15378
+ this.oView.byId("detail").setBindingContext(oContext);
15379
+
15380
+ await this.waitForChanges(assert, "detail");
15381
+
15382
+ for (let i = 0; i < 3; i += 1) {
15383
+ this.expectChange("link", null)
15384
+ .expectChange("link", sLink)
15385
+ .expectRequest({
15386
+ method : "PATCH",
15387
+ url : "Artists(ArtistID='42',IsActiveEntity=true)",
15388
+ payload : {Picture : null}
15389
+ })
15390
+ .expectRequest("Artists?$select=ArtistID,IsActiveEntity,Picture"
15391
+ + "&$filter=ArtistID eq '42' and IsActiveEntity eq true", {
15392
+ value : [{
15393
+ ArtistID : "42",
15394
+ IsActiveEntity : true,
15395
+ // Picture (Edm.Stream) missing here
15396
+ "Picture@odata.mediaContentType" : null
15397
+ }]
15398
+ })
15399
+ .expectChange("link", sLink); // due to "Picture@$ui5.noData : true" being set
15400
+
15401
+ // eslint-disable-next-line no-await-in-loop
15402
+ await Promise.all([
15403
+ oContext.setProperty("Picture", null),
15404
+ oContext.requestSideEffects(["Picture"]),
15405
+ oContext.setProperty("Picture", undefined, /*sGroupId*/null),
15406
+ this.waitForChanges(assert, "remove #" + i)
15407
+ ]);
15408
+ }
15409
+ });
15410
+
15258
15411
  //*********************************************************************************************
15259
15412
  // Scenario: Writing instance annotations via create and update.
15260
15413
  // 1. POST: Initial payload containing instance annotations
@@ -15676,7 +15829,9 @@ sap.ui.define([
15676
15829
 
15677
15830
  //*********************************************************************************************
15678
15831
  // Scenario: Minimal test for two absolute ODataPropertyBindings using different direct groups.
15679
- QUnit.test("Absolute ODPBs using different $direct groups", function (assert) {
15832
+ //
15833
+ // "sap-cancel-on-close" header for SubmitMode.Direct GET request (JIRA: CPOUI5ODATAV4-2506)
15834
+ QUnit.test("Absolute ODPBs using different direct groups", function (assert) {
15680
15835
  var sView = '\
15681
15836
  <Text id="text1" text="{\
15682
15837
  path : \'/EMPLOYEES(\\\'2\\\')/Name\',\
@@ -15686,8 +15841,14 @@ sap.ui.define([
15686
15841
  parameters : {$$groupId : \'group2\'}}"\
15687
15842
  />';
15688
15843
 
15689
- this.expectRequest("EMPLOYEES('2')/Name", {value : "Frederic Fall"})
15690
- .expectRequest("EMPLOYEES('3')/Name", {value : "Jonathan Smith"})
15844
+ this.expectRequest({
15845
+ headers : {"sap-cancel-on-close" : "true"},
15846
+ url : "EMPLOYEES('2')/Name"
15847
+ }, {value : "Frederic Fall"})
15848
+ .expectRequest({
15849
+ headers : {"sap-cancel-on-close" : "true"},
15850
+ url : "EMPLOYEES('3')/Name"
15851
+ }, {value : "Jonathan Smith"})
15691
15852
  .expectChange("text1", "Frederic Fall")
15692
15853
  .expectChange("text2", "Jonathan Smith");
15693
15854
 
@@ -15961,16 +16122,16 @@ sap.ui.define([
15961
16122
 
15962
16123
  return Promise.all([
15963
16124
  // code under test
15964
- that.oView.byId("function").getObjectBinding().execute(),
16125
+ that.oView.byId("function").getObjectBinding().invoke(),
15965
16126
  that.waitForChanges(assert)
15966
16127
  ]);
15967
16128
  });
15968
16129
  });
15969
16130
 
15970
16131
  //*********************************************************************************************
15971
- // Scenario: Operation binding for a function, first it is deferred, later is has been executed.
15972
- // Show interaction of setParameter(), execute() and refresh().
15973
- QUnit.test("Function binding: setParameter, execute and refresh", function (assert) {
16132
+ // Scenario: Operation binding for a function, first it is deferred, later is has been invoked.
16133
+ // Show interaction of setParameter(), invoke() and refresh().
16134
+ QUnit.test("Function binding: setParameter, invoke and refresh", function (assert) {
15974
16135
  var oFunctionBinding,
15975
16136
  sView = '\
15976
16137
  <FlexBox id="function" binding="{/GetEmployeeByID(...)}">\
@@ -15983,7 +16144,7 @@ sap.ui.define([
15983
16144
  return this.createView(assert, sView).then(function () {
15984
16145
  oFunctionBinding = that.oView.byId("function").getObjectBinding();
15985
16146
 
15986
- oFunctionBinding.refresh(); // MUST NOT trigger a request!
16147
+ oFunctionBinding.refresh(); // MUST NOT invoke a request!
15987
16148
 
15988
16149
  that.expectRequest("GetEmployeeByID(EmployeeID='1')", {
15989
16150
  ID : "1",
@@ -15992,7 +16153,7 @@ sap.ui.define([
15992
16153
  .expectChange("name", "Jonathan Smith");
15993
16154
 
15994
16155
  return Promise.all([
15995
- oFunctionBinding.setParameter("EmployeeID", "1").execute(),
16156
+ oFunctionBinding.setParameter("EmployeeID", "1").invoke(),
15996
16157
  that.waitForChanges(assert)
15997
16158
  ]);
15998
16159
  }).then(function () {
@@ -16007,7 +16168,7 @@ sap.ui.define([
16007
16168
  }).then(function () {
16008
16169
  oFunctionBinding.setParameter("EmployeeID", "2");
16009
16170
 
16010
- oFunctionBinding.refresh(); // MUST NOT trigger a request!
16171
+ oFunctionBinding.refresh(); // MUST NOT invoke a request!
16011
16172
 
16012
16173
  that.expectRequest("GetEmployeeByID(EmployeeID='2')", {
16013
16174
  ID : "2",
@@ -16016,7 +16177,7 @@ sap.ui.define([
16016
16177
  .expectChange("name", "Peter Burke");
16017
16178
 
16018
16179
  return Promise.all([
16019
- oFunctionBinding.execute(),
16180
+ oFunctionBinding.invoke(),
16020
16181
  that.waitForChanges(assert)
16021
16182
  ]);
16022
16183
  }).then(function () {
@@ -16032,9 +16193,9 @@ sap.ui.define([
16032
16193
  });
16033
16194
 
16034
16195
  //*********************************************************************************************
16035
- // Scenario: Operation binding for a function, first it is deferred, later is has been executed.
16036
- // Show interaction of setParameter(), execute() and changeParameters().
16037
- QUnit.test("Function binding: setParameter, execute and changeParameters", function (assert) {
16196
+ // Scenario: Operation binding for a function, first it is deferred, later is has been invoked.
16197
+ // Show interaction of setParameter(), invoke() and changeParameters().
16198
+ QUnit.test("Function binding: setParameter, invoke and changeParameters", function (assert) {
16038
16199
  var oFunctionBinding,
16039
16200
  sView = '\
16040
16201
  <FlexBox id="function" binding="{/GetEmployeeByID(...)}">\
@@ -16047,7 +16208,7 @@ sap.ui.define([
16047
16208
  return this.createView(assert, sView).then(function () {
16048
16209
  oFunctionBinding = that.oView.byId("function").getObjectBinding();
16049
16210
 
16050
- oFunctionBinding.changeParameters({$select : "Name"}); // MUST NOT trigger a request!
16211
+ oFunctionBinding.changeParameters({$select : "Name"}); // MUST NOT invoke a request!
16051
16212
 
16052
16213
  that.expectRequest("GetEmployeeByID(EmployeeID='1')?$select=Name", {
16053
16214
  Name : "Jonathan Smith"
@@ -16055,7 +16216,7 @@ sap.ui.define([
16055
16216
  .expectChange("name", "Jonathan Smith");
16056
16217
 
16057
16218
  return Promise.all([
16058
- oFunctionBinding.setParameter("EmployeeID", "1").execute(),
16219
+ oFunctionBinding.setParameter("EmployeeID", "1").invoke(),
16059
16220
  that.waitForChanges(assert)
16060
16221
  ]);
16061
16222
  }).then(function () {
@@ -16070,7 +16231,7 @@ sap.ui.define([
16070
16231
  }).then(function () {
16071
16232
  oFunctionBinding.setParameter("EmployeeID", "2");
16072
16233
 
16073
- // MUST NOT trigger a request!
16234
+ // MUST NOT invoke a request!
16074
16235
  oFunctionBinding.changeParameters({$select : "Name"});
16075
16236
 
16076
16237
  that.expectRequest("GetEmployeeByID(EmployeeID='2')?$select=Name", {
@@ -16079,7 +16240,7 @@ sap.ui.define([
16079
16240
  .expectChange("name", "Peter Burke");
16080
16241
 
16081
16242
  return Promise.all([
16082
- oFunctionBinding.execute(),
16243
+ oFunctionBinding.invoke(),
16083
16244
  that.waitForChanges(assert)
16084
16245
  ]);
16085
16246
  }).then(function () {
@@ -16636,7 +16797,7 @@ sap.ui.define([
16636
16797
 
16637
16798
  return Promise.all([
16638
16799
  // code under test
16639
- oActionBinding.setParameter("TeamID", "TEAM_02").execute()
16800
+ oActionBinding.setParameter("TeamID", "TEAM_02").invoke()
16640
16801
  .then(function (oReturnValueContext) {
16641
16802
  assert.strictEqual(oReturnValueContext.getPath(), "/EMPLOYEES('2')");
16642
16803
  }),
@@ -16717,7 +16878,7 @@ sap.ui.define([
16717
16878
 
16718
16879
  return Promise.all([
16719
16880
  // code under test
16720
- oActionBinding.setParameter("TeamID", "TEAM_02").execute()
16881
+ oActionBinding.setParameter("TeamID", "TEAM_02").invoke()
16721
16882
  .then(function (oReturnValueContext) {
16722
16883
  assert.strictEqual(oReturnValueContext.getPath(), "/EMPLOYEES('2')");
16723
16884
  }),
@@ -16767,7 +16928,7 @@ sap.ui.define([
16767
16928
 
16768
16929
  return Promise.all([
16769
16930
  // code under test
16770
- oActionBinding.execute(),
16931
+ oActionBinding.invoke(),
16771
16932
  that.waitForChanges(assert)
16772
16933
  ]);
16773
16934
  }).then(function () {
@@ -16786,7 +16947,7 @@ sap.ui.define([
16786
16947
 
16787
16948
  return Promise.all([
16788
16949
  // code under test
16789
- oActionBinding.execute().then(function (oReturnValueContext) {
16950
+ oActionBinding.invoke().then(function (oReturnValueContext) {
16790
16951
  assert.strictEqual(oReturnValueContext.getPath(), "/EMPLOYEES('2')");
16791
16952
  }),
16792
16953
  that.waitForChanges(assert)
@@ -16887,7 +17048,7 @@ sap.ui.define([
16887
17048
  .setParameter("todate", "2017-08-10T23:59:59Z")
16888
17049
  .setParameter("cityfrom", "new york")
16889
17050
  .setParameter("cityto", "SAN FRANCISCO")
16890
- .execute(),
17051
+ .invoke(),
16891
17052
  that.waitForChanges(assert)
16892
17053
  ]).then(function () {
16893
17054
  var oListBinding = oModel.bindList("value", oContextBinding.getBoundContext()),
@@ -16937,7 +17098,7 @@ sap.ui.define([
16937
17098
  .expectChange("value", "2017-08-10T00:00:00Z");
16938
17099
 
16939
17100
  return Promise.all([
16940
- that.oView.byId("function").getObjectBinding().execute(),
17101
+ that.oView.byId("function").getObjectBinding().invoke(),
16941
17102
  that.waitForChanges(assert)
16942
17103
  ]);
16943
17104
  });
@@ -16967,7 +17128,7 @@ sap.ui.define([
16967
17128
  });
16968
17129
 
16969
17130
  return Promise.all([
16970
- oContextBinding.execute(),
17131
+ oContextBinding.invoke(),
16971
17132
  that.waitForChanges(assert)
16972
17133
  ]).then(function () {
16973
17134
  var oListBinding = oModel.bindList("value", oContextBinding.getBoundContext()),
@@ -17017,7 +17178,7 @@ sap.ui.define([
17017
17178
  });
17018
17179
 
17019
17180
  return Promise.all([
17020
- oContextBinding.setParameter("carrid", "AA").execute(),
17181
+ oContextBinding.setParameter("carrid", "AA").invoke(),
17021
17182
  that.waitForChanges(assert)
17022
17183
  ]).then(function () {
17023
17184
  var oListBinding = oModel.bindList("value", oContextBinding.getBoundContext()),
@@ -17090,7 +17251,7 @@ sap.ui.define([
17090
17251
  .expectChange("distance", "2,572.0000");
17091
17252
 
17092
17253
  return Promise.all([
17093
- that.oView.byId("function").getObjectBinding().execute(),
17254
+ that.oView.byId("function").getObjectBinding().invoke(),
17094
17255
  that.waitForChanges(assert)
17095
17256
  ]);
17096
17257
  });
@@ -17129,7 +17290,7 @@ sap.ui.define([
17129
17290
  .setParameter("guid", "0050568D-393C-1ED4-9D97-E65F0F3FCC23")
17130
17291
  .setParameter("fldate", "2017-08-10T00:00:00Z")
17131
17292
  .setParameter("flightTime", 42)
17132
- .execute(),
17293
+ .invoke(),
17133
17294
  that.waitForChanges(assert)
17134
17295
  ]);
17135
17296
  }).then(function () {
@@ -17188,7 +17349,7 @@ sap.ui.define([
17188
17349
  .expectChange("id1", "08/15");
17189
17350
 
17190
17351
  return Promise.all([
17191
- oContextBinding.execute(),
17352
+ oContextBinding.invoke(),
17192
17353
  that.waitForChanges(assert)
17193
17354
  ]).then(function () {
17194
17355
  assert.strictEqual(
@@ -17210,7 +17371,7 @@ sap.ui.define([
17210
17371
 
17211
17372
  return this.createView(assert, "", oModel).then(function () {
17212
17373
  //TODO In the V2 adapter case a function import is used instead of a bound action. So we
17213
- // need the key predicates which sometimes cannot be parsed from the URL. Trigger this
17374
+ // need the key predicates which sometimes cannot be parsed from the URL. Invoke this
17214
17375
  // request and wait for the result before calling the function import.
17215
17376
  //TODO What about the ETag which might be got from this fresh request? Really use it?
17216
17377
  that.expectRequest("SalesOrderLineItemSet(\'0815\',\'10\')/ToHeader", {
@@ -17232,7 +17393,7 @@ sap.ui.define([
17232
17393
  return Promise.all([
17233
17394
  // code under test
17234
17395
  oModel.bindContext("GWSAMPLE_BASIC.SalesOrder_Confirm(...)", oParentContext)
17235
- .execute(),
17396
+ .invoke(),
17236
17397
  that.waitForChanges(assert)
17237
17398
  ]);
17238
17399
  });
@@ -17285,7 +17446,7 @@ sap.ui.define([
17285
17446
  .expectChange("newPhone", "+49 (0)2102 69555");
17286
17447
 
17287
17448
  return Promise.all([
17288
- oContextBinding.setParameter("telephone", "+49 (0)2102 69555").execute(),
17449
+ oContextBinding.setParameter("telephone", "+49 (0)2102 69555").invoke(),
17289
17450
  that.waitForChanges(assert)
17290
17451
  ]);
17291
17452
  });
@@ -18266,10 +18427,10 @@ sap.ui.define([
18266
18427
  });
18267
18428
 
18268
18429
  //*********************************************************************************************
18269
- // Scenario: Operation binding for a function, first it is deferred, later is has been executed.
18270
- // Show interaction of execute() and suspend()/resume(); setParameter() has been tested
18271
- // for refresh() already, see test "Function binding: setParameter, execute and refresh".
18272
- QUnit.test("Function binding: execute and suspend/resume", function (assert) {
18430
+ // Scenario: Operation binding for a function, first it is deferred, later is has been invoked.
18431
+ // Show interaction of invoke() and suspend()/resume(); setParameter() has been tested
18432
+ // for refresh() already, see test "Function binding: setParameter, invoke and refresh".
18433
+ QUnit.test("Function binding: invoke and suspend/resume", function (assert) {
18273
18434
  var oEmployeeBinding,
18274
18435
  sFunctionName = "com.sap.gateway.default.iwbep.tea_busi.v0001"
18275
18436
  + ".FuGetEmployeeSalaryForecast",
@@ -18304,7 +18465,7 @@ sap.ui.define([
18304
18465
  .expectChange("forecastSalary", "142");
18305
18466
 
18306
18467
  return Promise.all([
18307
- that.oView.byId("function").getObjectBinding().execute(),
18468
+ that.oView.byId("function").getObjectBinding().invoke(),
18308
18469
  that.waitForChanges(assert)
18309
18470
  ]);
18310
18471
  }).then(function () {
@@ -18735,7 +18896,7 @@ sap.ui.define([
18735
18896
  // code under test
18736
18897
  that.oView.byId("function").getObjectBinding()
18737
18898
  .setParameter("SalesOrderID", "0500000001")
18738
- .execute(),
18899
+ .invoke(),
18739
18900
  that.waitForChanges(assert)
18740
18901
  ]);
18741
18902
  });
@@ -20099,7 +20260,7 @@ sap.ui.define([
20099
20260
  .expectChange("active", [, "Yes"]);
20100
20261
 
20101
20262
  return Promise.all([
20102
- oAction.execute(undefined, false, null, /*bReplaceWithRVC*/true),
20263
+ oAction.invoke(undefined, false, null, /*bReplaceWithRVC*/true),
20103
20264
  that.waitForChanges(assert, "replace with active")
20104
20265
  ]);
20105
20266
  }).then(function (aResult) {
@@ -21097,7 +21258,7 @@ sap.ui.define([
21097
21258
  });
21098
21259
 
21099
21260
  //*********************************************************************************************
21100
- QUnit.test("delayed execute", function (assert) {
21261
+ QUnit.test("delayed invoke", function (assert) {
21101
21262
  var sAction = "SalesOrderList('0500000000')/"
21102
21263
  + "com.sap.gateway.default.zui5_epm_sample.v0002.SalesOrder_Cancel",
21103
21264
  oModel = this.createSalesOrdersModel(),
@@ -21112,7 +21273,7 @@ sap.ui.define([
21112
21273
  }, {SalesOrderID : "0500000000"});
21113
21274
 
21114
21275
  return Promise.all([
21115
- that.oView.byId("form").getElementBinding().execute("update"),
21276
+ that.oView.byId("form").getElementBinding().invoke("update"),
21116
21277
  that.oModel.submitBatch("update"),
21117
21278
  that.waitForChanges(assert)
21118
21279
  ]);
@@ -21121,7 +21282,7 @@ sap.ui.define([
21121
21282
 
21122
21283
  //*********************************************************************************************
21123
21284
  // Scenario: Refresh using a group with submit mode 'API'. The view contains one context binding
21124
- // without children. Hence the binding doesn't trigger a request, but its lock must be released.
21285
+ // without children. Hence the binding doesn't invoke a request, but its lock must be released.
21125
21286
  QUnit.test("ODCB: delayed refresh", function (assert) {
21126
21287
  var oModel = this.createSalesOrdersModel({autoExpandSelect : true}),
21127
21288
  sView = `
@@ -21157,7 +21318,7 @@ sap.ui.define([
21157
21318
 
21158
21319
  //*********************************************************************************************
21159
21320
  // Scenario: Refresh using a group with submit mode 'API'. The model contains one list binding
21160
- // without a control. Hence getContexts() is not called and no request is triggered. But the
21321
+ // without a control. Hence getContexts() is not called and no request is invoked. But the
21161
21322
  // lock must be released.
21162
21323
  QUnit.test("ODLB: delayed refresh", function (assert) {
21163
21324
  var oModel = this.createSalesOrdersModel({autoExpandSelect : true}),
@@ -25431,6 +25592,12 @@ sap.ui.define([
25431
25592
  [true, undefined, 1, "Friend #01"]
25432
25593
  ]);
25433
25594
 
25595
+ // Since CPOUI5ODATAV4-2493 selecting a header context will select all row contexts.
25596
+ // This behavior is undesired for this test scenario. Remove the selection but select
25597
+ // back the root node.
25598
+ oHeaderContext.setSelected(false);
25599
+ oRoot.setSelected(true);
25600
+
25434
25601
  assert.strictEqual(oListBinding.getCount(), 1, "count of nodes"); // code under test
25435
25602
 
25436
25603
  that.expectRequest("Artists(ArtistID='0',IsActiveEntity=true)?$select=defaultChannel", {
@@ -26107,7 +26274,7 @@ sap.ui.define([
26107
26274
  //*********************************************************************************************
26108
26275
  // Scenario: Show a recursive hierarchy with a single root node, expand to show a single child.
26109
26276
  // Edit non-hierarchy property with associated currency, also w/o sending a PATCH, for both root
26110
- // and child. Execute a bound action for both root and child to see that it updates the node.
26277
+ // and child. Invoke a bound action for both root and child to see that it updates the node.
26111
26278
  // JIRA: CPOUI5ODATAV4-1851
26112
26279
  //
26113
26280
  // Use relative ODLB with an initially suspended parent (JIRA: CPOUI5ODATAV4-1985 etc.)
@@ -26306,7 +26473,7 @@ sap.ui.define([
26306
26473
  return Promise.all([
26307
26474
  oModel.bindContext(sAction + "(...)", oRoot)
26308
26475
  .setParameter("TeamID", "TEAM_23")
26309
- .execute()
26476
+ .invoke()
26310
26477
  .then(function (oReturnValueContext) {
26311
26478
  assert.strictEqual(oRoot.getPath(),
26312
26479
  "/TEAMS('42')/TEAM_2_EMPLOYEES('0')");
@@ -26315,7 +26482,7 @@ sap.ui.define([
26315
26482
  }),
26316
26483
  oModel.bindContext(sAction + "(...)", oChild)
26317
26484
  .setParameter("TeamID", "TEAM_42")
26318
- .execute()
26485
+ .invoke()
26319
26486
  .then(function (oReturnValueContext) {
26320
26487
  // Note: RVC has iGeneration === 2 instead of 0
26321
26488
  assert.notStrictEqual(oReturnValueContext, oChild);
@@ -28638,10 +28805,16 @@ sap.ui.define([
28638
28805
  await this.createView(assert, sView, oModel);
28639
28806
 
28640
28807
  const oTable = this.oView.byId("table");
28808
+ const oAlpha = oTable.getItems()[0].getBindingContext();
28809
+
28810
+ assert.throws(function () {
28811
+ oAlpha.delete("deferred"); // code under test
28812
+ }, new Error("Unsupported group ID: deferred"));
28813
+
28641
28814
  this.expectRequest("DELETE EMPLOYEES('0')");
28642
28815
 
28643
28816
  await Promise.all([
28644
- oTable.getItems()[0].getBindingContext().delete(), // code under test
28817
+ oAlpha.delete(), // code under test
28645
28818
  this.waitForChanges(assert, "delete")
28646
28819
  ]);
28647
28820
 
@@ -29899,6 +30072,7 @@ sap.ui.define([
29899
30072
  // Create a new root via "@$ui5.node.parent" : null (JIRA: CPOUI5ODATAV4-2355)
29900
30073
  // Move "Beta" to make it a root node (JIRA: CPOUI5ODATAV4-2399)
29901
30074
  // Display NodeID on UI, request NodeID after creation (JIRA: CPOUI5ODATAV4-2381)
30075
+ // NodeID must ignore list's filters (SNOW: DINC0087713)
29902
30076
  //
29903
30077
  // "Refresh single" for stale elements; keep same context instance for created nodes throughout
29904
30078
  // collapse and side effects.
@@ -29911,15 +30085,17 @@ sap.ui.define([
29911
30085
 
29912
30086
  const oModel = this.createSpecialCasesModel({autoExpandSelect : true});
29913
30087
  const sFriend = "/Artists(ArtistID='99',IsActiveEntity=false)/_Friend";
29914
- const sBaseUrl = sFriend.slice(1) + "?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
29915
- + "HierarchyNodes=$root" + sFriend
30088
+ const sBaseUrl = sFriend.slice(1) + "?$apply=ancestors($root" + sFriend
30089
+ + ",OrgChart,_/NodeID,filter(sendsAutographs),keep start)"
30090
+ + "/com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root" + sFriend
29916
30091
  + ",HierarchyQualifier='OrgChart',NodeProperty='_/NodeID',Levels=1)";
29917
30092
  const sView = `
29918
30093
  <t:Table id="table" rows="{path : '/Artists(ArtistID=\\'99\\',IsActiveEntity=false)/_Friend',
29919
30094
  parameters : {
29920
30095
  $$aggregation : {
29921
30096
  hierarchyQualifier : 'OrgChart'
29922
- }
30097
+ },
30098
+ $filter : 'sendsAutographs'
29923
30099
  }}" threshold="0" visibleRowCount="3">
29924
30100
  <Text text="{= %{@$ui5.context.isTransient} }"/>
29925
30101
  <Text text="{= %{@$ui5.node.isExpanded} }"/>
@@ -29953,6 +30129,10 @@ sap.ui.define([
29953
30129
  oTable = that.oView.byId("table");
29954
30130
  oRoot = oTable.getRows()[0].getBindingContext();
29955
30131
  oListBinding = oRoot.getBinding();
30132
+ assert.throws(function () {
30133
+ // code under test
30134
+ oListBinding.getHeaderContext().move();
30135
+ }, new Error("Cannot move " + sFriend));
29956
30136
 
29957
30137
  checkTable("root is leaf", assert, oTable, [
29958
30138
  sFriend + "(ArtistID='0',IsActiveEntity=false)"
@@ -29994,6 +30174,10 @@ sap.ui.define([
29994
30174
  Name : "Beta"
29995
30175
  }, /*bSkipRefresh*/true);
29996
30176
  oBetaCreated = oBeta.created();
30177
+ assert.throws(function () {
30178
+ // code under test
30179
+ oBeta.move();
30180
+ }, new Error("Cannot move " + oBeta), "too early");
29997
30181
 
29998
30182
  return Promise.all([
29999
30183
  checkCanceled(assert, oLostChild.created()),
@@ -30011,6 +30195,7 @@ sap.ui.define([
30011
30195
 
30012
30196
  that.expectChange("etag", [, "etag1.0"])
30013
30197
  .expectChange("name", [, "Beta: β"])
30198
+ // no "filter(sendsAutographs)" (SNOW: DINC0087713)
30014
30199
  .expectRequest(sFriend.slice(1) + "?$apply=descendants($root" + sFriend
30015
30200
  + ",OrgChart,_/NodeID,filter(ArtistID eq '0' and IsActiveEntity eq false),1)"
30016
30201
  + "&$filter=ArtistID eq '1' and IsActiveEntity eq false&$select=_/NodeID", {
@@ -30075,6 +30260,7 @@ sap.ui.define([
30075
30260
  })
30076
30261
  .expectChange("etag", [, "etag2.0"])
30077
30262
  .expectChange("name", [, "Gamma: γ"])
30263
+ // no "filter(sendsAutographs)" (SNOW: DINC0087713)
30078
30264
  .expectRequest(sFriend.slice(1) + "?$apply=descendants($root" + sFriend
30079
30265
  + ",OrgChart,_/NodeID,filter(ArtistID eq '0' and IsActiveEntity eq false),1)"
30080
30266
  + "&$filter=ArtistID eq '2' and IsActiveEntity eq false&$select=_/NodeID", {
@@ -30253,8 +30439,9 @@ sap.ui.define([
30253
30439
  assert.strictEqual(oBeta.getModel(), oModel, "not destroyed by collapse");
30254
30440
  assert.strictEqual(oGamma.getModel(), oModel, "not destroyed by collapse");
30255
30441
 
30256
- that.expectRequest(sFriend.slice(1) + "?$select=ArtistID,IsActiveEntity,Name,_/NodeID"
30257
- + "&$filter=ArtistID eq '0' and IsActiveEntity eq false", {
30442
+ that.expectRequest(sFriend.slice(1)
30443
+ + "?$filter=ArtistID eq '0' and IsActiveEntity eq false"
30444
+ + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID", {
30258
30445
  value : [{
30259
30446
  "@odata.etag" : "etag0.1",
30260
30447
  ArtistID : "0",
@@ -30431,7 +30618,10 @@ sap.ui.define([
30431
30618
  })
30432
30619
  .expectChange("etag", ["etag9.0"])
30433
30620
  .expectChange("name", ["Aleph: ℵ"])
30434
- .expectRequest(sBaseUrl
30621
+ // no "filter(sendsAutographs)" (SNOW: DINC0087713)
30622
+ .expectRequest(sFriend.slice(1) + "?$apply="
30623
+ + "com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root" + sFriend
30624
+ + ",HierarchyQualifier='OrgChart',NodeProperty='_/NodeID',Levels=1)"
30435
30625
  + "&$filter=ArtistID eq '9' and IsActiveEntity eq false&$select=_/NodeID", {
30436
30626
  value : [{
30437
30627
  "@odata.etag" : "etag9.0",
@@ -30466,11 +30656,12 @@ sap.ui.define([
30466
30656
  ]);
30467
30657
  checkCreatedPersisted(assert, oNewRoot);
30468
30658
 
30469
- that.expectRequest(sFriend.slice(1) + "?$select=ArtistID,IsActiveEntity,Name,_/NodeID"
30470
- + "&$filter=ArtistID eq '9' and IsActiveEntity eq false"
30659
+ that.expectRequest(sFriend.slice(1)
30660
+ + "?$filter=ArtistID eq '9' and IsActiveEntity eq false"
30471
30661
  + " or ArtistID eq '0' and IsActiveEntity eq false"
30472
30662
  + " or ArtistID eq '2' and IsActiveEntity eq false"
30473
30663
  + " or ArtistID eq '1' and IsActiveEntity eq false"
30664
+ + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
30474
30665
  + "&$top=4", {
30475
30666
  value : [{
30476
30667
  "@odata.etag" : "etag9.1",
@@ -30577,15 +30768,16 @@ sap.ui.define([
30577
30768
 
30578
30769
  //*********************************************************************************************
30579
30770
  // Scenario: Create a new node when all levels are expanded, observe a GET for LimitedRank. The
30580
- // created node is inserted on the second sibling position on back end, but is shown on the
30581
- // client on first position. Use a filter and a search as well as a sort order. Before creation,
30582
- // a sibling is collapsed and after creation it is expanded again. The root is collapsed and
30583
- // immediately expanded again. Finally, the new node is deleted again.
30771
+ // created node is inserted on the second sibling position on back end and is shown on the
30772
+ // client "in place" (JIRA: CPOUI5ODATAV4-2466). Use a filter and a search as well as a sort
30773
+ // order. Before creation, a sibling is collapsed and after creation it is expanded again. The
30774
+ // root is collapsed and immediately expanded again. Finally, the new node is deleted again.
30584
30775
  // JIRA: CPOUI5ODATAV4-2393
30585
30776
  //
30586
30777
  // Before deletion, the new node is maybe moved to make it a root (JIRA: CPOUI5ODATAV4-2400)
30587
30778
  // Old vs. new format of RecursiveHierarchy annotation (JIRA: CPOUI5ODATAV4-2401)
30588
30779
  // Display NodeID on UI, request NodeID after creation (JIRA: CPOUI5ODATAV4-2381)
30780
+ // NodeID must ignore list's filters (SNOW: DINC0087713)
30589
30781
  //
30590
30782
  // At first, create a new root node with a LimitedRank beyond all currently loaded nodes.
30591
30783
  // Finally, it is also deleted.
@@ -30700,11 +30892,27 @@ make root = ${bMakeRoot}`;
30700
30892
  Name : "Aleph",
30701
30893
  _ : null // not available w/ RAP for a non-hierarchical request
30702
30894
  })
30703
- .expectRequest(sBaseUrl + "&$filter=ArtistID eq '8' and IsActiveEntity eq false"
30704
- + "&$select=_/" + sLimitedRank + ",_/NodeID", {
30895
+ .expectRequest({
30896
+ batchNo : 3,
30897
+ url : sBaseUrl + "&$filter=ArtistID eq '8' and IsActiveEntity eq false"
30898
+ + "&$select=_/" + sLimitedRank
30899
+ }, {
30900
+ value : [{
30901
+ _ : {
30902
+ [sLimitedRank] : "10" // Edm.Int64
30903
+ }
30904
+ }]
30905
+ })
30906
+ .expectRequest({
30907
+ batchNo : 3,
30908
+ // no "filter(...)/search(...)" (SNOW: DINC0087713)
30909
+ url : sFriend.slice(1) + "?$apply="
30910
+ + "com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root" + sFriend
30911
+ + ",HierarchyQualifier='" + sHierarchyQualifier + "',NodeProperty='_/NodeID')"
30912
+ + "&$filter=ArtistID eq '8' and IsActiveEntity eq false&$select=_/NodeID"
30913
+ }, {
30705
30914
  value : [{
30706
30915
  _ : {
30707
- [sLimitedRank] : "10", // Edm.Int64
30708
30916
  NodeID : "8,false"
30709
30917
  }
30710
30918
  }]
@@ -30845,11 +31053,27 @@ make root = ${bMakeRoot}`;
30845
31053
  Name : "New",
30846
31054
  _ : null // not available w/ RAP for a non-hierarchical request
30847
31055
  })
30848
- .expectRequest(sBaseUrl + "&$filter=ArtistID eq '9' and IsActiveEntity eq false"
30849
- + "&$select=_/" + sLimitedRank + ",_/NodeID", {
31056
+ .expectRequest({
31057
+ batchNo : 7,
31058
+ url : sBaseUrl + "&$filter=ArtistID eq '9' and IsActiveEntity eq false"
31059
+ + "&$select=_/" + sLimitedRank
31060
+ }, {
31061
+ value : [{
31062
+ _ : {
31063
+ [sLimitedRank] : "4" // Edm.Int64
31064
+ }
31065
+ }]
31066
+ })
31067
+ .expectRequest({
31068
+ batchNo : 7,
31069
+ // no "filter(...)/search(...)" (SNOW: DINC0087713)
31070
+ url : sFriend.slice(1) + "?$apply="
31071
+ + "com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root" + sFriend
31072
+ + ",HierarchyQualifier='" + sHierarchyQualifier + "',NodeProperty='_/NodeID')"
31073
+ + "&$filter=ArtistID eq '9' and IsActiveEntity eq false&$select=_/NodeID"
31074
+ }, {
30850
31075
  value : [{
30851
31076
  _ : {
30852
- [sLimitedRank] : "4", // Edm.Int64
30853
31077
  NodeID : "9,false"
30854
31078
  }
30855
31079
  }]
@@ -31005,9 +31229,10 @@ make root = ${bMakeRoot}`;
31005
31229
  this.waitForChanges(assert, "make New a root node")
31006
31230
  ]);
31007
31231
 
31232
+ checkPersisted(assert, oNewChild);
31233
+
31008
31234
  await this.checkAllContexts("after make New a root node", assert, oListBinding,
31009
31235
  ["@$ui5.node.isExpanded", "@$ui5.node.level", "ArtistID", "Name", "_/NodeID"], [
31010
- [undefined, 1, "9", "New", "9,false"],
31011
31236
  [undefined, 1, "8", "Aleph", "8,false"],
31012
31237
  [true, 1, "0", "Alpha", "0,false"],
31013
31238
  [undefined, 2, "1", "Beta", "1,false"],
@@ -31018,16 +31243,24 @@ make root = ${bMakeRoot}`;
31018
31243
  [undefined, 3, "5.1", "Eta", "5.1,false"],
31019
31244
  [undefined, 3, "5.2", "Theta", "5.2,false"],
31020
31245
  [undefined, 2, "6", "Iota", "6,false"],
31021
- [undefined, 2, "7", "Kappa", "7,false"]
31246
+ [undefined, 2, "7", "Kappa", "7,false"],
31247
+ [undefined, 1, "9", "New", "9,false"]
31022
31248
  ]);
31023
31249
  }
31024
31250
 
31025
31251
  this.expectRequest("DELETE Artists(ArtistID='8',IsActiveEntity=false)")
31026
31252
  .expectRequest("DELETE Artists(ArtistID='9',IsActiveEntity=false)");
31027
31253
 
31028
- await Promise.all([
31254
+ // code under test
31255
+ const oDeleteNewRootPromise = oNewRoot.delete();
31256
+
31257
+ assert.throws(function () {
31029
31258
  // code under test
31030
- oNewRoot.delete(),
31259
+ oNewRoot.move();
31260
+ }, new Error("Cannot move " + oNewRoot), "too late");
31261
+
31262
+ await Promise.all([
31263
+ oDeleteNewRootPromise,
31031
31264
  // code under test
31032
31265
  oNewChild.delete(),
31033
31266
  this.waitForChanges(assert, "delete New")
@@ -31853,7 +32086,7 @@ make root = ${bMakeRoot}`;
31853
32086
  });
31854
32087
 
31855
32088
  //*********************************************************************************************
31856
- // Scenario: A hierarchy has an initial expandTo=1 and three visible rows. Expand and collapse
32089
+ // Scenario: A hierarchy has an initial expand all and three visible rows. Expand and collapse
31857
32090
  // various nodes and request side effects.
31858
32091
  // (1) Collapse Beta -> Alpha, Beta, Delta
31859
32092
  // (2) Request side effects -> Delta is removed -> Alpha, Beta, Epsilon
@@ -32258,22 +32491,32 @@ make root = ${bMakeRoot}`;
32258
32491
  // create New6 below New3
32259
32492
  // (3) Side-effects refresh (-> unified cache; New2 is already read in-place, it is shifted when
32260
32493
  // moving New1 to its out-of-place position; Beta is already read in-place, but shifted
32261
- // when moving New1 and New3; Gamma is only placeholder when moving New5)
32494
+ // when moving New1 and New3; Gamma is only placeholder when moving New5).
32495
+ // Additionally request the first row in parallel just like the tree table occasionally
32496
+ // does, this must not cause further requests.
32262
32497
  // (4) Check all contexts
32263
- // (5) Refresh the binding (out of place is no longer kept, tree is collapsed again to 1 level)
32498
+ // (5) Delete New1 (no longer requested as out-of-place node afterward)
32499
+ // (6) Side-effects refresh (moves New3 below Gamma)
32500
+ // (7) Check all contexts
32501
+ // (8) Side-effects refresh (New3 and New6 are no longer requested as out-of-place nodes)
32502
+ // (9) Delete Alpha
32503
+ // (10) Side-effects refresh (expand state and out-of-place information are dropped for Alpha's
32504
+ // descendants)
32505
+ // (11) Refresh the binding (out-of-place information is no longer kept, tree is collapsed again
32506
+ // to 1 level)
32264
32507
  // JIRA: CPOUI5ODATAV4-2454
32265
32508
  QUnit.test("Recursive Hierarchy: out of place", async function (assert) {
32266
32509
  const oModel = this.createSpecialCasesModel({autoExpandSelect : true});
32267
- const sFriend = "/Artists(ArtistID='99',IsActiveEntity=false)/_Friend";
32510
+ const sFriend = "Artists(ArtistID='99',IsActiveEntity=false)/_Friend";
32268
32511
  const sFilterSearchPrefix = "ancestors("
32269
- + "$root" + sFriend + ",OrgChart,_/NodeID,"
32512
+ + "$root/" + sFriend + ",OrgChart,_/NodeID,"
32270
32513
  + "filter(IsActiveEntity eq false)/search(covfefe),keep start)/";
32271
- const baseUrl = (sExpandLevels) => sFriend.slice(1)
32514
+ const baseUrl = (sExpandLevels) => sFriend
32272
32515
  + "?custom=foo&$apply=" + sFilterSearchPrefix + "orderby(defaultChannel)"
32273
- + "/com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root" + sFriend
32516
+ + "/com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root/" + sFriend
32274
32517
  + ",HierarchyQualifier='OrgChart',NodeProperty='_/NodeID',Levels=1"
32275
32518
  + (sExpandLevels ? ",ExpandLevels=" + sExpandLevels : "") + ")";
32276
- const sCountUrl = sFriend.slice(1) + "/$count?$filter=IsActiveEntity eq false&custom=foo"
32519
+ const sCountUrl = sFriend + "/$count?$filter=IsActiveEntity eq false&custom=foo"
32277
32520
  + "&$search=covfefe";
32278
32521
  const sExpandLevels = JSON.stringify([
32279
32522
  {NodeID : "1,false", Levels : 1},
@@ -32281,6 +32524,10 @@ make root = ${bMakeRoot}`;
32281
32524
  {NodeID : "3,false", Levels : 1},
32282
32525
  {NodeID : "13,false", Levels : 1}
32283
32526
  ]);
32527
+ const sExpandLevelsAfterDelete = JSON.stringify([
32528
+ {NodeID : "3,false", Levels : 1},
32529
+ {NodeID : "13,false", Levels : 1}
32530
+ ]);
32284
32531
  const sView = `
32285
32532
  <t:Table id="table" rows="{path : '/Artists(ArtistID=\\'99\\',IsActiveEntity=false)/_Friend',
32286
32533
  parameters : {
@@ -32299,17 +32546,17 @@ make root = ${bMakeRoot}`;
32299
32546
  <Text text="{Name}"/>
32300
32547
  </t:Table>`;
32301
32548
 
32302
- // Server: UI:
32303
- // 1 Alpha 1 Alpha
32304
- // 12 New2 (created) 13 New3 (created)
32305
- // 2 Beta 16 New6 (created)
32306
- // 14 New4 (created) 12 New2 (created)
32307
- // 11 New1 (created) 11 New1 (created)
32308
- // 13 New3 (created) 2 Beta
32309
- // 16 New6 (created) 14 New4 (created)
32310
- // 3 Gamma 3 Gamma
32311
- // 15 New5 (created) 15 New5 (created)
32312
- // 4 Delta 4 Delta
32549
+ // Server: UI:
32550
+ // 1 Alpha 1 Alpha
32551
+ // 12 New2 13 New3
32552
+ // 2 Beta 16 New6
32553
+ // 14 New4 12 New2
32554
+ // 11 New1 11 New1
32555
+ // 13 New3 2 Beta
32556
+ // 16 New6 14 New4
32557
+ // 3 Gamma 3 Gamma
32558
+ // 15 New5 15 New5
32559
+ // 4 Delta 4 Delta
32313
32560
  this.expectRequest(sCountUrl, 4)
32314
32561
  .expectRequest(baseUrl()
32315
32562
  + "&$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID"
@@ -32347,9 +32594,9 @@ make root = ${bMakeRoot}`;
32347
32594
  const oTable = this.oView.byId("table");
32348
32595
  const oBinding = oTable.getBinding("rows");
32349
32596
  checkTable("initial page", assert, oTable, [
32350
- sFriend + "(ArtistID='1',IsActiveEntity=false)",
32351
- sFriend + "(ArtistID='3',IsActiveEntity=false)",
32352
- sFriend + "(ArtistID='4',IsActiveEntity=false)"
32597
+ `/${sFriend}(ArtistID='1',IsActiveEntity=false)`,
32598
+ `/${sFriend}(ArtistID='3',IsActiveEntity=false)`,
32599
+ `/${sFriend}(ArtistID='4',IsActiveEntity=false)`
32353
32600
  ], [
32354
32601
  [false, 1, "1", "Alpha"],
32355
32602
  [undefined, 1, "3", "Gamma"],
@@ -32358,8 +32605,8 @@ make root = ${bMakeRoot}`;
32358
32605
  const oAlpha = oTable.getRows()[0].getBindingContext();
32359
32606
  const oGamma = oTable.getRows()[1].getBindingContext();
32360
32607
 
32361
- this.expectRequest(sFriend.slice(1) + "?custom=foo&$apply=" + sFilterSearchPrefix
32362
- + "descendants($root/" + sFriend.slice(1)
32608
+ this.expectRequest(sFriend + "?custom=foo&$apply=" + sFilterSearchPrefix
32609
+ + "descendants($root/" + sFriend
32363
32610
  + ",OrgChart,_/NodeID,filter(ArtistID eq '1' and IsActiveEntity eq false),1)"
32364
32611
  + "/orderby(defaultChannel)"
32365
32612
  + "&$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID"
@@ -32381,10 +32628,10 @@ make root = ${bMakeRoot}`;
32381
32628
  await this.waitForChanges(assert, "(1) expand Alpha");
32382
32629
 
32383
32630
  checkTable("after (1)", assert, oTable, [
32384
- sFriend + "(ArtistID='1',IsActiveEntity=false)",
32385
- sFriend + "(ArtistID='2',IsActiveEntity=false)",
32386
- sFriend + "(ArtistID='3',IsActiveEntity=false)",
32387
- sFriend + "(ArtistID='4',IsActiveEntity=false)"
32631
+ `/${sFriend}(ArtistID='1',IsActiveEntity=false)`,
32632
+ `/${sFriend}(ArtistID='2',IsActiveEntity=false)`,
32633
+ `/${sFriend}(ArtistID='3',IsActiveEntity=false)`,
32634
+ `/${sFriend}(ArtistID='4',IsActiveEntity=false)`
32388
32635
  ], [
32389
32636
  [true, 1, "1", "Alpha"],
32390
32637
  [undefined, 2, "2", "Beta"],
@@ -32396,7 +32643,7 @@ make root = ${bMakeRoot}`;
32396
32643
  const sParentId = oParent.getProperty("ArtistID");
32397
32644
  this.expectRequest({
32398
32645
  method : "POST",
32399
- url : sFriend.slice(1) + "?custom=foo",
32646
+ url : sFriend + "?custom=foo",
32400
32647
  payload : {
32401
32648
  "BestFriend@odata.bind" :
32402
32649
  `../Artists(ArtistID='${sParentId}',IsActiveEntity=false)`,
@@ -32408,11 +32655,10 @@ make root = ${bMakeRoot}`;
32408
32655
  Name : sName,
32409
32656
  _ : null // not available w/ RAP for a non-hierarchical request
32410
32657
  })
32411
- .expectRequest(sFriend.slice(1) + "?$apply=" + sFilterSearchPrefix
32412
- + "descendants($root/" + sFriend.slice(1)
32658
+ // no sFilterSearchPrefix (SNOW: DINC0087713)
32659
+ .expectRequest(sFriend + "?custom=foo&$apply=descendants($root/" + sFriend
32413
32660
  + ",OrgChart,_/NodeID,filter(ArtistID eq '" + sParentId
32414
32661
  + "' and IsActiveEntity eq false),1)"
32415
- + "/orderby(defaultChannel)"
32416
32662
  + "&$filter=ArtistID eq '" + sId
32417
32663
  + "' and IsActiveEntity eq false&$select=_/NodeID", {
32418
32664
  value : [{
@@ -32422,14 +32668,17 @@ make root = ${bMakeRoot}`;
32422
32668
  }]
32423
32669
  });
32424
32670
 
32425
- const oContext = oBinding.create({
32426
- "@$ui5.node.parent" : oParent,
32427
- Name : sName
32428
- }, /*bSkipRefresh*/true);
32671
+ const oContext = oBinding.create({
32672
+ "@$ui5.node.parent" : oParent,
32673
+ Name : sName
32674
+ }, /*bSkipRefresh*/true);
32429
32675
 
32430
- await oContext.created();
32676
+ await Promise.all([
32677
+ oContext.created(),
32678
+ this.waitForChanges(assert, `(2) create ${sName}`)
32679
+ ]);
32431
32680
 
32432
- return oContext;
32681
+ return oContext;
32433
32682
  };
32434
32683
 
32435
32684
  await create("11", "New1", oAlpha);
@@ -32437,24 +32686,19 @@ make root = ${bMakeRoot}`;
32437
32686
  const oNew3 = await create("13", "New3", oAlpha);
32438
32687
  await create("14", "New4", oBeta);
32439
32688
  await create("15", "New5", oGamma);
32440
-
32441
- await this.waitForChanges(assert, "(2a) create nodes");
32442
-
32443
- const oNew6 = await create("16", "New6", oNew3);
32444
-
32445
- await this.waitForChanges(assert, "(2b) create nested node");
32689
+ const oNew6 = await create("16", "New6", oNew3); // nested below New3
32446
32690
 
32447
32691
  checkTable("after (2)", assert, oTable, [
32448
- sFriend + "(ArtistID='1',IsActiveEntity=false)",
32449
- sFriend + "(ArtistID='13',IsActiveEntity=false)",
32450
- sFriend + "(ArtistID='16',IsActiveEntity=false)",
32451
- sFriend + "(ArtistID='12',IsActiveEntity=false)",
32452
- sFriend + "(ArtistID='11',IsActiveEntity=false)",
32453
- sFriend + "(ArtistID='2',IsActiveEntity=false)",
32454
- sFriend + "(ArtistID='14',IsActiveEntity=false)",
32455
- sFriend + "(ArtistID='3',IsActiveEntity=false)",
32456
- sFriend + "(ArtistID='15',IsActiveEntity=false)",
32457
- sFriend + "(ArtistID='4',IsActiveEntity=false)"
32692
+ `/${sFriend}(ArtistID='1',IsActiveEntity=false)`,
32693
+ `/${sFriend}(ArtistID='13',IsActiveEntity=false)`,
32694
+ `/${sFriend}(ArtistID='16',IsActiveEntity=false)`,
32695
+ `/${sFriend}(ArtistID='12',IsActiveEntity=false)`,
32696
+ `/${sFriend}(ArtistID='11',IsActiveEntity=false)`,
32697
+ `/${sFriend}(ArtistID='2',IsActiveEntity=false)`,
32698
+ `/${sFriend}(ArtistID='14',IsActiveEntity=false)`,
32699
+ `/${sFriend}(ArtistID='3',IsActiveEntity=false)`,
32700
+ `/${sFriend}(ArtistID='15',IsActiveEntity=false)`,
32701
+ `/${sFriend}(ArtistID='4',IsActiveEntity=false)`
32458
32702
  ], [
32459
32703
  [true, 1, "1", "Alpha"],
32460
32704
  [true, 2, "13", "New3"],
@@ -32603,7 +32847,7 @@ make root = ${bMakeRoot}`;
32603
32847
  })
32604
32848
  .expectRequest({
32605
32849
  batchNo : 15,
32606
- url : sFriend.slice(1) + "?custom=foo&$apply=descendants($root/" + sFriend.slice(1)
32850
+ url : sFriend + "?custom=foo&$apply=descendants($root/" + sFriend
32607
32851
  + ",OrgChart,_/NodeID,filter(ArtistID eq '1' and IsActiveEntity eq false),1)"
32608
32852
  + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
32609
32853
  + "&$filter=ArtistID eq '11' and IsActiveEntity eq false"
@@ -32636,7 +32880,7 @@ make root = ${bMakeRoot}`;
32636
32880
  })
32637
32881
  .expectRequest({
32638
32882
  batchNo : 15,
32639
- url : sFriend.slice(1) + "?custom=foo&$apply=descendants($root/" + sFriend.slice(1)
32883
+ url : sFriend + "?custom=foo&$apply=descendants($root/" + sFriend
32640
32884
  + ",OrgChart,_/NodeID,filter(ArtistID eq '2' and IsActiveEntity eq false),1)"
32641
32885
  + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
32642
32886
  + "&$filter=ArtistID eq '14' and IsActiveEntity eq false"
@@ -32653,7 +32897,7 @@ make root = ${bMakeRoot}`;
32653
32897
  })
32654
32898
  .expectRequest({
32655
32899
  batchNo : 15,
32656
- url : sFriend.slice(1) + "?custom=foo&$apply=descendants($root/" + sFriend.slice(1)
32900
+ url : sFriend + "?custom=foo&$apply=descendants($root/" + sFriend
32657
32901
  + ",OrgChart,_/NodeID,filter(ArtistID eq '3' and IsActiveEntity eq false),1)"
32658
32902
  + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
32659
32903
  + "&$filter=ArtistID eq '15' and IsActiveEntity eq false"
@@ -32670,7 +32914,7 @@ make root = ${bMakeRoot}`;
32670
32914
  })
32671
32915
  .expectRequest({
32672
32916
  batchNo : 15,
32673
- url : sFriend.slice(1) + "?custom=foo&$apply=descendants($root/" + sFriend.slice(1)
32917
+ url : sFriend + "?custom=foo&$apply=descendants($root/" + sFriend
32674
32918
  + ",OrgChart,_/NodeID,filter(ArtistID eq '13' and IsActiveEntity eq false),1)"
32675
32919
  + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
32676
32920
  + "&$filter=ArtistID eq '16' and IsActiveEntity eq false"
@@ -32689,18 +32933,20 @@ make root = ${bMakeRoot}`;
32689
32933
  await Promise.all([
32690
32934
  // code under test
32691
32935
  oBinding.getHeaderContext().requestSideEffects([""]),
32936
+ // code under test: requesting one row already covered by side-effects refresh
32937
+ oBinding.getContexts(0, 1),
32692
32938
  this.waitForChanges(assert, "(3) side-effects refresh")
32693
32939
  ]);
32694
32940
 
32695
32941
  checkTable("after (3)", assert, oTable, [
32696
- sFriend + "(ArtistID='1',IsActiveEntity=false)",
32697
- sFriend + "(ArtistID='13',IsActiveEntity=false)",
32698
- sFriend + "(ArtistID='16',IsActiveEntity=false)",
32699
- sFriend + "(ArtistID='12',IsActiveEntity=false)",
32700
- sFriend + "(ArtistID='11',IsActiveEntity=false)",
32701
- sFriend + "(ArtistID='2',IsActiveEntity=false)",
32702
- sFriend + "(ArtistID='14',IsActiveEntity=false)",
32703
- sFriend + "(ArtistID='15',IsActiveEntity=false)"
32942
+ `/${sFriend}(ArtistID='1',IsActiveEntity=false)`,
32943
+ `/${sFriend}(ArtistID='13',IsActiveEntity=false)`,
32944
+ `/${sFriend}(ArtistID='16',IsActiveEntity=false)`,
32945
+ `/${sFriend}(ArtistID='12',IsActiveEntity=false)`,
32946
+ `/${sFriend}(ArtistID='11',IsActiveEntity=false)`,
32947
+ `/${sFriend}(ArtistID='2',IsActiveEntity=false)`,
32948
+ `/${sFriend}(ArtistID='14',IsActiveEntity=false)`,
32949
+ `/${sFriend}(ArtistID='15',IsActiveEntity=false)`
32704
32950
  ], [
32705
32951
  [true, 1, "1", "Alpha*"],
32706
32952
  [true, 2, "13", "New3*"],
@@ -32757,23 +33003,595 @@ make root = ${bMakeRoot}`;
32757
33003
  [undefined, 1, "4", "Delta*"]
32758
33004
  ]);
32759
33005
 
32760
- this.expectRequest(sCountUrl, 10)
32761
- .expectRequest(baseUrl()
32762
- + "&$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID"
33006
+ // this context has been destroyed by the refresh because it was not visible
33007
+ const [oNew1] = await oBinding.requestContexts(4, 1);
33008
+
33009
+ this.expectRequest("DELETE Artists(ArtistID='11',IsActiveEntity=false)");
33010
+
33011
+ await Promise.all([
33012
+ // code under test
33013
+ oNew1.delete(),
33014
+ this.waitForChanges(assert, "(5) delete New1")
33015
+ ]);
33016
+
33017
+ // After deleting New1 & side-effects refresh
33018
+ // Server: UI:
33019
+ // 1 Alpha 1 Alpha
33020
+ // 12 New2 12 New2 (out of place)
33021
+ // 2 Beta 2 Beta
33022
+ // 14 New4 14 New4 (out of place)
33023
+ // 3 Gamma 3 Gamma
33024
+ // 13 New3 (moved) 15 New5 (out of place)
33025
+ // 16 New6 13 New3 (moved)
33026
+ // 15 New5 16 New6
33027
+ // 4 Delta 4 Delta
33028
+
33029
+ this.expectRequest(sCountUrl, 9)
33030
+ .expectRequest(baseUrl(sExpandLevels)
33031
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DescendantCount,_/DistanceFromRoot"
33032
+ + ",_/DrillState,_/NodeID"
32763
33033
  + "&$count=true&$skip=0&$top=3", {
32764
- "@odata.count" : "3",
33034
+ "@odata.count" : "9",
32765
33035
  value : [{
32766
33036
  ArtistID : "1",
32767
33037
  IsActiveEntity : false,
32768
33038
  Name : "Alpha**",
32769
33039
  _ : {
32770
- DrillState : "collapsed",
33040
+ DescendantCount : "3",
33041
+ DistanceFromRoot : "0",
33042
+ DrillState : "expanded",
33043
+ NodeID : "1,false"
33044
+ }
33045
+ }, {
33046
+ ArtistID : "12",
33047
+ IsActiveEntity : false,
33048
+ Name : "New2**",
33049
+ _ : {
33050
+ DescendantCount : "0",
33051
+ DistanceFromRoot : "1",
33052
+ DrillState : "leaf",
33053
+ NodeID : "12,false"
33054
+ }
33055
+ }, {
33056
+ ArtistID : "2",
33057
+ IsActiveEntity : false,
33058
+ Name : "Beta**",
33059
+ _ : {
33060
+ DescendantCount : "1",
33061
+ DistanceFromRoot : "1",
33062
+ DrillState : "expanded",
33063
+ NodeID : "2,false"
33064
+ }
33065
+ }]
33066
+ })
33067
+ .expectRequest(baseUrl(sExpandLevels)
33068
+ + "&$select=ArtistID,IsActiveEntity,_/DescendantCount,_/DistanceFromRoot"
33069
+ + ",_/DrillState,_/Limited_Rank"
33070
+ + "&$filter=ArtistID eq '1' and IsActiveEntity eq false"
33071
+ + " or ArtistID eq '12' and IsActiveEntity eq false"
33072
+ + " or ArtistID eq '13' and IsActiveEntity eq false"
33073
+ + " or ArtistID eq '14' and IsActiveEntity eq false"
33074
+ + " or ArtistID eq '15' and IsActiveEntity eq false"
33075
+ + " or ArtistID eq '16' and IsActiveEntity eq false"
33076
+ + " or ArtistID eq '2' and IsActiveEntity eq false"
33077
+ + " or ArtistID eq '3' and IsActiveEntity eq false"
33078
+ + "&$top=8", {
33079
+ value : [{
33080
+ ArtistID : "1",
33081
+ IsActiveEntity : false,
33082
+ _ : {
33083
+ DescendantCount : "3",
33084
+ DistanceFromRoot : "n/a", // parent's DistanceFromRoot is not yet relevant
33085
+ DrillState : "expanded",
33086
+ Limited_Rank : "0"
33087
+ }
33088
+ }, {
33089
+ ArtistID : "12",
33090
+ IsActiveEntity : false,
33091
+ _ : {
33092
+ DescendantCount : "0",
33093
+ DistanceFromRoot : "1",
33094
+ DrillState : "leaf",
33095
+ Limited_Rank : "1"
33096
+ }
33097
+ }, {
33098
+ ArtistID : "2",
33099
+ IsActiveEntity : false,
33100
+ _ : {
33101
+ DescendantCount : "1",
33102
+ DistanceFromRoot : "n/a", // parent's DistanceFromRoot is not yet relevant
33103
+ DrillState : "expanded",
33104
+ Limited_Rank : "2"
33105
+ }
33106
+ }, {
33107
+ ArtistID : "14",
33108
+ IsActiveEntity : false,
33109
+ _ : {
33110
+ DescendantCount : "0",
33111
+ DistanceFromRoot : "2",
33112
+ DrillState : "leaf",
33113
+ Limited_Rank : "3"
33114
+ }
33115
+ }, {
33116
+ ArtistID : "3",
33117
+ IsActiveEntity : false,
33118
+ _ : {
33119
+ DescendantCount : "3",
33120
+ DistanceFromRoot : "n/a", // parent's DistanceFromRoot is not yet relevant
33121
+ DrillState : "expanded",
33122
+ Limited_Rank : "4"
33123
+ }
33124
+ }, {
33125
+ ArtistID : "13",
33126
+ IsActiveEntity : false,
33127
+ _ : {
33128
+ DescendantCount : "1",
33129
+ DistanceFromRoot : "1",
33130
+ DrillState : "expanded",
33131
+ Limited_Rank : "5"
33132
+ }
33133
+ }, {
33134
+ ArtistID : "16",
33135
+ IsActiveEntity : false,
33136
+ _ : {
33137
+ DescendantCount : "0",
33138
+ DistanceFromRoot : "2",
33139
+ DrillState : "leaf",
33140
+ Limited_Rank : "6"
33141
+ }
33142
+ }, {
33143
+ ArtistID : "15",
33144
+ IsActiveEntity : false,
33145
+ _ : {
33146
+ DescendantCount : "0",
33147
+ DistanceFromRoot : "1",
33148
+ DrillState : "leaf",
33149
+ Limited_Rank : "7"
33150
+ }
33151
+ }]
33152
+ })
33153
+ .expectRequest(sFriend
33154
+ + "?custom=foo&$apply=descendants($root/" + sFriend
33155
+ + ",OrgChart,_/NodeID,filter(ArtistID eq '1' and IsActiveEntity eq false),1)"
33156
+ + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
33157
+ + "&$filter=ArtistID eq '12' and IsActiveEntity eq false"
33158
+ + " or ArtistID eq '13' and IsActiveEntity eq false"
33159
+ + "&$top=2", {
33160
+ value : [{
33161
+ ArtistID : "12",
33162
+ IsActiveEntity : false,
33163
+ Name : "New2**",
33164
+ _ : {
33165
+ NodeID : "12,false"
33166
+ }
33167
+ }]
33168
+ })
33169
+ .expectRequest(sFriend
33170
+ + "?custom=foo&$apply=descendants($root/" + sFriend
33171
+ + ",OrgChart,_/NodeID,filter(ArtistID eq '2' and IsActiveEntity eq false),1)"
33172
+ + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
33173
+ + "&$filter=ArtistID eq '14' and IsActiveEntity eq false"
33174
+ + "&$top=1", {
33175
+ value : [{
33176
+ ArtistID : "14",
33177
+ IsActiveEntity : false,
33178
+ Name : "New4**",
33179
+ _ : {
33180
+ NodeID : "14,false"
33181
+ }
33182
+ }]
33183
+ })
33184
+ .expectRequest(sFriend
33185
+ + "?custom=foo&$apply=descendants($root/" + sFriend
33186
+ + ",OrgChart,_/NodeID,filter(ArtistID eq '3' and IsActiveEntity eq false),1)"
33187
+ + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
33188
+ + "&$filter=ArtistID eq '15' and IsActiveEntity eq false"
33189
+ + "&$top=1", {
33190
+ value : [{
33191
+ ArtistID : "15",
33192
+ IsActiveEntity : false,
33193
+ Name : "New5**",
33194
+ _ : {
33195
+ NodeID : "15,false"
33196
+ }
33197
+ }]
33198
+ })
33199
+ .expectRequest(sFriend
33200
+ + "?custom=foo&$apply=descendants($root/" + sFriend
33201
+ + ",OrgChart,_/NodeID,filter(ArtistID eq '13' and IsActiveEntity eq false),1)"
33202
+ + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
33203
+ + "&$filter=ArtistID eq '16' and IsActiveEntity eq false"
33204
+ + "&$top=1", {
33205
+ value : [{
33206
+ ArtistID : "16",
33207
+ IsActiveEntity : false,
33208
+ Name : "New6**",
33209
+ _ : {
33210
+ NodeID : "16,false"
33211
+ }
33212
+ }]
33213
+ });
33214
+
33215
+ await Promise.all([
33216
+ // code under test
33217
+ oBinding.getHeaderContext().requestSideEffects([""]),
33218
+ this.waitForChanges(assert, "(6) side-effects refresh")
33219
+ ]);
33220
+
33221
+ this.expectRequest(baseUrl(sExpandLevels)
33222
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DescendantCount,_/DistanceFromRoot"
33223
+ + ",_/DrillState,_/NodeID"
33224
+ + "&$skip=4&$top=1", {
33225
+ value : [{
33226
+ ArtistID : "3",
33227
+ IsActiveEntity : false,
33228
+ Name : "Gamma**",
33229
+ _ : {
33230
+ DescendantCount : "3",
33231
+ DistanceFromRoot : "0",
33232
+ DrillState : "expanded",
33233
+ NodeID : "3,false"
33234
+ }
33235
+ }]
33236
+ })
33237
+ .expectRequest(baseUrl(sExpandLevels)
33238
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DescendantCount,_/DistanceFromRoot"
33239
+ + ",_/DrillState,_/NodeID"
33240
+ + "&$skip=5&$top=1", {
33241
+ value : [{
33242
+ ArtistID : "13",
33243
+ IsActiveEntity : false,
33244
+ Name : "New3**",
33245
+ _ : {
33246
+ DescendantCount : "1",
33247
+ DistanceFromRoot : "1",
33248
+ DrillState : "expanded",
33249
+ NodeID : "13,false"
33250
+ }
33251
+ }]
33252
+ })
33253
+ .expectRequest(baseUrl(sExpandLevels)
33254
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DescendantCount,_/DistanceFromRoot"
33255
+ + ",_/DrillState,_/NodeID"
33256
+ + "&$skip=8&$top=1", {
33257
+ value : [{
33258
+ ArtistID : "4",
33259
+ IsActiveEntity : false,
33260
+ Name : "Delta**",
33261
+ _ : {
33262
+ DescendantCount : "0",
33263
+ DistanceFromRoot : "0",
33264
+ DrillState : "leaf",
33265
+ NodeID : "4,false"
33266
+ }
33267
+ }]
33268
+ });
33269
+
33270
+ await this.checkAllContexts("(7) check all contexts", assert, oBinding,
33271
+ ["@$ui5.node.isExpanded", "@$ui5.node.level", "ArtistID", "Name"], [
33272
+ [true, 1, "1", "Alpha**"],
33273
+ [undefined, 2, "12", "New2**"],
33274
+ [true, 2, "2", "Beta**"],
33275
+ [undefined, 3, "14", "New4**"],
33276
+ [true, 1, "3", "Gamma**"],
33277
+ [undefined, 2, "15", "New5**"],
33278
+ [true, 2, "13", "New3**"],
33279
+ [undefined, 3, "16", "New6**"],
33280
+ [undefined, 1, "4", "Delta**"]
33281
+ ]);
33282
+
33283
+ this.expectRequest(sCountUrl, 9)
33284
+ .expectRequest(baseUrl(sExpandLevels)
33285
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DescendantCount,_/DistanceFromRoot"
33286
+ + ",_/DrillState,_/NodeID"
33287
+ + "&$count=true&$skip=0&$top=3", {
33288
+ "@odata.count" : "9",
33289
+ value : [{
33290
+ ArtistID : "1",
33291
+ IsActiveEntity : false,
33292
+ Name : "Alpha**",
33293
+ _ : {
33294
+ DescendantCount : "3",
33295
+ DistanceFromRoot : "0",
33296
+ DrillState : "expanded",
32771
33297
  NodeID : "1,false"
32772
33298
  }
32773
33299
  }, {
33300
+ ArtistID : "12",
33301
+ IsActiveEntity : false,
33302
+ Name : "New2**",
33303
+ _ : {
33304
+ DescendantCount : "0",
33305
+ DistanceFromRoot : "1",
33306
+ DrillState : "leaf",
33307
+ NodeID : "12,false"
33308
+ }
33309
+ }, {
33310
+ ArtistID : "2",
33311
+ IsActiveEntity : false,
33312
+ Name : "Beta**",
33313
+ _ : {
33314
+ DescendantCount : "1",
33315
+ DistanceFromRoot : "1",
33316
+ DrillState : "expanded",
33317
+ NodeID : "2,false"
33318
+ }
33319
+ }]
33320
+ })
33321
+ .expectRequest(baseUrl(sExpandLevels)
33322
+ + "&$select=ArtistID,IsActiveEntity,_/DescendantCount,_/DistanceFromRoot"
33323
+ + ",_/DrillState,_/Limited_Rank"
33324
+ + "&$filter=ArtistID eq '1' and IsActiveEntity eq false"
33325
+ + " or ArtistID eq '12' and IsActiveEntity eq false"
33326
+ + " or ArtistID eq '14' and IsActiveEntity eq false"
33327
+ + " or ArtistID eq '15' and IsActiveEntity eq false"
33328
+ + " or ArtistID eq '2' and IsActiveEntity eq false"
33329
+ + " or ArtistID eq '3' and IsActiveEntity eq false"
33330
+ + "&$top=6", {
33331
+ value : [{
33332
+ ArtistID : "1",
33333
+ IsActiveEntity : false,
33334
+ _ : {
33335
+ DescendantCount : "3",
33336
+ DistanceFromRoot : "n/a", // parent's DistanceFromRoot is not yet relevant
33337
+ DrillState : "expanded",
33338
+ Limited_Rank : "0"
33339
+ }
33340
+ }, {
33341
+ ArtistID : "12",
33342
+ IsActiveEntity : false,
33343
+ _ : {
33344
+ DescendantCount : "0",
33345
+ DistanceFromRoot : "1",
33346
+ DrillState : "leaf",
33347
+ Limited_Rank : "1"
33348
+ }
33349
+ }, {
33350
+ ArtistID : "2",
33351
+ IsActiveEntity : false,
33352
+ _ : {
33353
+ DescendantCount : "1",
33354
+ DistanceFromRoot : "n/a", // parent's DistanceFromRoot is not yet relevant
33355
+ DrillState : "expanded",
33356
+ Limited_Rank : "2"
33357
+ }
33358
+ }, {
33359
+ ArtistID : "14",
33360
+ IsActiveEntity : false,
33361
+ _ : {
33362
+ DescendantCount : "0",
33363
+ DistanceFromRoot : "2",
33364
+ DrillState : "leaf",
33365
+ Limited_Rank : "3"
33366
+ }
33367
+ }, {
33368
+ ArtistID : "3",
33369
+ IsActiveEntity : false,
33370
+ _ : {
33371
+ DescendantCount : "3",
33372
+ DistanceFromRoot : "n/a", // parent's DistanceFromRoot is not yet relevant
33373
+ DrillState : "expanded",
33374
+ Limited_Rank : "4"
33375
+ }
33376
+ }, {
33377
+ ArtistID : "15",
33378
+ IsActiveEntity : false,
33379
+ _ : {
33380
+ DescendantCount : "0",
33381
+ DistanceFromRoot : "1",
33382
+ DrillState : "leaf",
33383
+ Limited_Rank : "7"
33384
+ }
33385
+ }]
33386
+ })
33387
+ .expectRequest(sFriend
33388
+ + "?custom=foo&$apply=descendants($root/" + sFriend
33389
+ + ",OrgChart,_/NodeID,filter(ArtistID eq '1' and IsActiveEntity eq false),1)"
33390
+ + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
33391
+ + "&$filter=ArtistID eq '12' and IsActiveEntity eq false"
33392
+ + "&$top=1", {
33393
+ value : [{
33394
+ ArtistID : "12",
33395
+ IsActiveEntity : false,
33396
+ Name : "New2**",
33397
+ _ : {
33398
+ NodeID : "12,false"
33399
+ }
33400
+ }]
33401
+ })
33402
+ .expectRequest(sFriend
33403
+ + "?custom=foo&$apply=descendants($root/" + sFriend
33404
+ + ",OrgChart,_/NodeID,filter(ArtistID eq '2' and IsActiveEntity eq false),1)"
33405
+ + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
33406
+ + "&$filter=ArtistID eq '14' and IsActiveEntity eq false"
33407
+ + "&$top=1", {
33408
+ value : [{
33409
+ ArtistID : "14",
33410
+ IsActiveEntity : false,
33411
+ Name : "New4**",
33412
+ _ : {
33413
+ NodeID : "14,false"
33414
+ }
33415
+ }]
33416
+ })
33417
+ .expectRequest(sFriend
33418
+ + "?custom=foo&$apply=descendants($root/" + sFriend
33419
+ + ",OrgChart,_/NodeID,filter(ArtistID eq '3' and IsActiveEntity eq false),1)"
33420
+ + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
33421
+ + "&$filter=ArtistID eq '15' and IsActiveEntity eq false"
33422
+ + "&$top=1", {
33423
+ value : [{
33424
+ ArtistID : "15",
33425
+ IsActiveEntity : false,
33426
+ Name : "New5**",
33427
+ _ : {
33428
+ NodeID : "15,false"
33429
+ }
33430
+ }]
33431
+ });
33432
+
33433
+ await Promise.all([
33434
+ // code under test
33435
+ oBinding.getHeaderContext().requestSideEffects([""]),
33436
+ this.waitForChanges(assert, "(8) side-effects refresh")
33437
+ ]);
33438
+
33439
+ this.expectRequest("DELETE Artists(ArtistID='1',IsActiveEntity=false)")
33440
+ .expectRequest(baseUrl(sExpandLevels)
33441
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DescendantCount,_/DistanceFromRoot"
33442
+ + ",_/DrillState,_/NodeID"
33443
+ + "&$skip=0&$top=1", {
33444
+ value : [{
32774
33445
  ArtistID : "3",
32775
33446
  IsActiveEntity : false,
32776
33447
  Name : "Gamma**",
33448
+ _ : {
33449
+ DescendantCount : "3",
33450
+ DistanceFromRoot : "0",
33451
+ DrillState : "expanded",
33452
+ NodeID : "3,false"
33453
+ }
33454
+ }]
33455
+ })
33456
+ .expectRequest(baseUrl(sExpandLevels)
33457
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DescendantCount,_/DistanceFromRoot"
33458
+ + ",_/DrillState,_/NodeID"
33459
+ + "&$skip=1&$top=1", {
33460
+ value : [{
33461
+ ArtistID : "13",
33462
+ IsActiveEntity : false,
33463
+ Name : "New3**",
33464
+ _ : {
33465
+ DescendantCount : "1",
33466
+ DistanceFromRoot : "1",
33467
+ DrillState : "expanded",
33468
+ NodeID : "13,false"
33469
+ }
33470
+ }]
33471
+ });
33472
+
33473
+ await Promise.all([
33474
+ // code under test
33475
+ oAlpha.delete(),
33476
+ this.waitForChanges(assert, "(9) delete Alpha")
33477
+ ]);
33478
+
33479
+ checkTable("after (9)", assert, oTable, [
33480
+ `/${sFriend}(ArtistID='3',IsActiveEntity=false)`,
33481
+ `/${sFriend}(ArtistID='15',IsActiveEntity=false)`,
33482
+ `/${sFriend}(ArtistID='13',IsActiveEntity=false)`
33483
+ ], [
33484
+ [true, 1, "3", "Gamma**"],
33485
+ [undefined, 2, "15", "New5**"],
33486
+ [true, 2, "13", "New3**"]
33487
+ ], 5);
33488
+
33489
+ this.expectRequest(sCountUrl, 5)
33490
+ .expectRequest(baseUrl(sExpandLevelsAfterDelete)
33491
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DescendantCount,_/DistanceFromRoot"
33492
+ + ",_/DrillState,_/NodeID"
33493
+ + "&$count=true&$skip=0&$top=3", {
33494
+ "@odata.count" : "5",
33495
+ value : [{
33496
+ ArtistID : "3",
33497
+ IsActiveEntity : false,
33498
+ Name : "Gamma**",
33499
+ _ : {
33500
+ DescendantCount : "3",
33501
+ DistanceFromRoot : "0",
33502
+ DrillState : "expanded",
33503
+ NodeID : "3,false"
33504
+ }
33505
+ }, {
33506
+ ArtistID : "13",
33507
+ IsActiveEntity : false,
33508
+ Name : "New3**",
33509
+ _ : {
33510
+ DescendantCount : "1",
33511
+ DistanceFromRoot : "1",
33512
+ DrillState : "expanded",
33513
+ NodeID : "13,false"
33514
+ }
33515
+ }, {
33516
+ ArtistID : "16",
33517
+ IsActiveEntity : false,
33518
+ Name : "New6**",
33519
+ _ : {
33520
+ DescendantCount : "0",
33521
+ DistanceFromRoot : "2",
33522
+ DrillState : "leaf",
33523
+ NodeID : "16,false"
33524
+ }
33525
+ }]
33526
+ })
33527
+ .expectRequest(baseUrl(sExpandLevelsAfterDelete)
33528
+ + "&$select=ArtistID,IsActiveEntity,_/DescendantCount,_/DistanceFromRoot"
33529
+ + ",_/DrillState,_/Limited_Rank"
33530
+ + "&$filter=ArtistID eq '15' and IsActiveEntity eq false"
33531
+ + " or ArtistID eq '3' and IsActiveEntity eq false"
33532
+ + "&$top=2", {
33533
+ value : [{
33534
+ ArtistID : "3",
33535
+ IsActiveEntity : false,
33536
+ _ : {
33537
+ DescendantCount : "3",
33538
+ DistanceFromRoot : "n/a", // parent's DistanceFromRoot is not yet relevant
33539
+ DrillState : "expanded",
33540
+ Limited_Rank : "0"
33541
+ }
33542
+ }, {
33543
+ ArtistID : "15",
33544
+ IsActiveEntity : false,
33545
+ _ : {
33546
+ DescendantCount : "0",
33547
+ DistanceFromRoot : "1",
33548
+ DrillState : "leaf",
33549
+ Limited_Rank : "3"
33550
+ }
33551
+ }]
33552
+ })
33553
+ .expectRequest(sFriend
33554
+ + "?custom=foo&$apply=descendants($root/" + sFriend
33555
+ + ",OrgChart,_/NodeID,filter(ArtistID eq '3' and IsActiveEntity eq false),1)"
33556
+ + "&$select=ArtistID,IsActiveEntity,Name,_/NodeID"
33557
+ + "&$filter=ArtistID eq '15' and IsActiveEntity eq false"
33558
+ + "&$top=1", {
33559
+ value : [{
33560
+ ArtistID : "15",
33561
+ IsActiveEntity : false,
33562
+ Name : "New5**",
33563
+ _ : {
33564
+ NodeID : "15,false"
33565
+ }
33566
+ }]
33567
+ });
33568
+
33569
+ await Promise.all([
33570
+ // code under test
33571
+ oBinding.getHeaderContext().requestSideEffects([""]),
33572
+ this.waitForChanges(assert, "(10) side-effects refresh")
33573
+ ]);
33574
+
33575
+ checkTable("after (10)", assert, oTable, [
33576
+ `/${sFriend}(ArtistID='3',IsActiveEntity=false)`,
33577
+ `/${sFriend}(ArtistID='15',IsActiveEntity=false)`,
33578
+ `/${sFriend}(ArtistID='13',IsActiveEntity=false)`,
33579
+ `/${sFriend}(ArtistID='16',IsActiveEntity=false)`
33580
+ ], [
33581
+ [true, 1, "3", "Gamma**"],
33582
+ [undefined, 2, "15", "New5**"],
33583
+ [true, 2, "13", "New3**"]
33584
+ ], 5);
33585
+
33586
+ this.expectRequest(sCountUrl, 5)
33587
+ .expectRequest(baseUrl()
33588
+ + "&$select=ArtistID,IsActiveEntity,Name,_/DrillState,_/NodeID"
33589
+ + "&$count=true&$skip=0&$top=3", {
33590
+ "@odata.count" : "2",
33591
+ value : [{
33592
+ ArtistID : "3",
33593
+ IsActiveEntity : false,
33594
+ Name : "Gamma***",
32777
33595
  _ : {
32778
33596
  DrillState : "collapsed",
32779
33597
  NodeID : "3,false"
@@ -32781,7 +33599,7 @@ make root = ${bMakeRoot}`;
32781
33599
  }, {
32782
33600
  ArtistID : "4",
32783
33601
  IsActiveEntity : false,
32784
- Name : "Delta**",
33602
+ Name : "Delta***",
32785
33603
  _ : {
32786
33604
  DrillState : "leaf",
32787
33605
  NodeID : "4,false"
@@ -32789,30 +33607,29 @@ make root = ${bMakeRoot}`;
32789
33607
  }]
32790
33608
  });
32791
33609
 
32792
- oBinding.refresh();
32793
-
32794
- await this.waitForChanges(assert, "(5) refresh the binding");
33610
+ await Promise.all([
33611
+ oBinding.requestRefresh(),
33612
+ this.waitForChanges(assert, "(11) refresh the binding")
33613
+ ]);
32795
33614
 
32796
- checkTable("after (5)", assert, oTable, [
32797
- sFriend + "(ArtistID='1',IsActiveEntity=false)",
32798
- sFriend + "(ArtistID='3',IsActiveEntity=false)",
32799
- sFriend + "(ArtistID='4',IsActiveEntity=false)"
33615
+ checkTable("after (11)", assert, oTable, [
33616
+ `/${sFriend}(ArtistID='3',IsActiveEntity=false)`,
33617
+ `/${sFriend}(ArtistID='4',IsActiveEntity=false)`
32800
33618
  ], [
32801
- [false, 1, "1", "Alpha**"],
32802
- [false, 1, "3", "Gamma**"],
32803
- [undefined, 1, "4", "Delta**"]
33619
+ [false, 1, "3", "Gamma***"],
33620
+ [undefined, 1, "4", "Delta***"]
32804
33621
  ]);
32805
33622
  });
32806
33623
 
32807
33624
  //*********************************************************************************************
32808
33625
  // Scenario: A hierarchy has two visible rows, expandTo 2, and first visible row 2.
32809
33626
  // (1) Collapse Gamma
32810
- // (2) Create two root nodes Zeta and Eta which the server puts at the end
33627
+ // (2) Create root nodes Zeta and Eta which the server puts at the end; create Theta below Alpha
32811
33628
  // (3) Side-effects refresh (-> unified cache; after having read the in-place data, the created
32812
33629
  // nodes are moved to the front and the in-place range is shifted)
32813
33630
  // (4) Check all contexts
32814
33631
  // JIRA: CPOUI5ODATAV4-2454
32815
- QUnit.test("Recursive Hierarchy: out of place, root nodes", async function (assert) {
33632
+ QUnit.test("Recursive Hierarchy: out of place, root, expandTo > 1", async function (assert) {
32816
33633
  const oModel = this.createTeaBusiModel({autoExpandSelect : true});
32817
33634
  const sCountUrl = "EMPLOYEES/$count?$filter=AGE gt 20&custom=foo&$search=covfefe";
32818
33635
  const sFilterSearchPrefix = "ancestors($root/EMPLOYEES,OrgChart,ID,filter(AGE gt 20)"
@@ -32821,8 +33638,8 @@ make root = ${bMakeRoot}`;
32821
33638
  + "?custom=foo&$apply=" + sFilterSearchPrefix + "orderby(ENTRYDATE)"
32822
33639
  + "/com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root/EMPLOYEES"
32823
33640
  + ",HierarchyQualifier='OrgChart',NodeProperty='ID',Levels=2)";
32824
- const sUrlWithExpandLevels = sUrl.slice(0, -1)
32825
- + ",ExpandLevels=" + JSON.stringify([{NodeID : "3", Levels : 0}]) + ")";
33641
+ const sUrlWithExpandLevels = sUrl.slice(0, -1) + ",ExpandLevels="
33642
+ + JSON.stringify([{NodeID : "3", Levels : 0}, {NodeID : "1", Levels : 1}]) + ")";
32826
33643
  const sView = `
32827
33644
  <t:Table id="table" firstVisibleRow="2" rows="{path : '/EMPLOYEES',
32828
33645
  parameters : {
@@ -32842,6 +33659,7 @@ make root = ${bMakeRoot}`;
32842
33659
  </t:Table>`;
32843
33660
 
32844
33661
  // 1 Alpha
33662
+ // 8 Theta (created)
32845
33663
  // 2 Beta
32846
33664
  // 3 Gamma (first visible row)
32847
33665
  // 4 Delta
@@ -32923,8 +33741,7 @@ make root = ${bMakeRoot}`;
32923
33741
  Name : "Beta"
32924
33742
  }]
32925
33743
  })
32926
- .expectRequest(sUrl.replace("custom=foo&", "")
32927
- + "&$filter=ID eq '6'&$select=LimitedRank",
33744
+ .expectRequest(sUrl + "&$filter=ID eq '6'&$select=LimitedRank",
32928
33745
  {value : [{LimitedRank : "5"}]});
32929
33746
 
32930
33747
  const oZeta = oBinding.create({Name : "Zeta"}, /*bSkipRefresh*/true);
@@ -32937,8 +33754,7 @@ make root = ${bMakeRoot}`;
32937
33754
  this.expectRequest(
32938
33755
  {method : "POST", url : "EMPLOYEES?custom=foo", payload : {Name : "Eta"}},
32939
33756
  {ID : "7", Name : "Eta"})
32940
- .expectRequest(sUrl.replace("custom=foo&", "")
32941
- + "&$filter=ID eq '7'&$select=LimitedRank",
33757
+ .expectRequest(sUrl + "&$filter=ID eq '7'&$select=LimitedRank",
32942
33758
  {value : [{LimitedRank : "6"}]});
32943
33759
 
32944
33760
  const oEta = oBinding.create({Name : "Eta"}, /*bSkipRefresh*/true);
@@ -32948,32 +33764,61 @@ make root = ${bMakeRoot}`;
32948
33764
  this.waitForChanges(assert, "(2b) create Eta")
32949
33765
  ]);
32950
33766
 
33767
+ this.expectRequest({
33768
+ method : "POST",
33769
+ url : "EMPLOYEES?custom=foo",
33770
+ payload : {
33771
+ "EMPLOYEE_2_MANAGER@odata.bind" : "EMPLOYEES('1')",
33772
+ Name : "Theta"
33773
+ }
33774
+ }, {ID : "8", Name : "Theta"})
33775
+ .expectRequest(sUrl + "&$filter=ID eq '8'&$select=LimitedRank",
33776
+ {value : [{LimitedRank : "1"}]});
33777
+
33778
+ const oAlpha = oTable.getRows()[0].getBindingContext();
33779
+ const oTheta = oBinding.create({
33780
+ "@$ui5.node.parent" : oAlpha,
33781
+ Name : "Theta"
33782
+ }, /*bSkipRefresh*/true);
33783
+
33784
+ await Promise.all([
33785
+ oTheta.created(),
33786
+ this.waitForChanges(assert, "(2c) create Theta")
33787
+ ]);
33788
+
32951
33789
  checkTable("after (2)", assert, oTable, [
32952
33790
  "/EMPLOYEES('7')",
32953
33791
  "/EMPLOYEES('6')",
32954
33792
  "/EMPLOYEES('1')",
33793
+ "/EMPLOYEES('8')",
32955
33794
  "/EMPLOYEES('2')",
32956
33795
  "/EMPLOYEES('3')",
32957
33796
  "/EMPLOYEES('5')"
32958
33797
  ], [
32959
- [undefined, 1, "Alpha"],
32960
- [undefined, 1, "Beta"]
33798
+ [true, 1, "Alpha"],
33799
+ [undefined, 2, "Theta"]
32961
33800
  ]);
32962
33801
 
32963
- this.expectRequest(sCountUrl, 7)
33802
+ this.expectRequest(sCountUrl, 8)
32964
33803
  .expectRequest({
32965
- batchNo : 7,
33804
+ batchNo : 9,
32966
33805
  url : sUrlWithExpandLevels
32967
33806
  + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,Name"
32968
33807
  + "&$count=true&$skip=0&$top=4"
32969
33808
  }, {
32970
- "@odata.count" : "6",
33809
+ "@odata.count" : "7",
32971
33810
  value : [{
32972
- DescendantCount : "0",
33811
+ DescendantCount : "1",
32973
33812
  DistanceFromRoot : "0",
32974
- DrillState : "leaf",
33813
+ DrillState : "expanded",
32975
33814
  ID : "1",
32976
33815
  Name : "Alpha*"
33816
+ }, {
33817
+ DescendantCount : "0",
33818
+ DistanceFromRoot : "1",
33819
+ DrillState : "leaf",
33820
+ ID : "8",
33821
+ Name : "Theta*"
32977
33822
  }, {
32978
33823
  DescendantCount : "0",
32979
33824
  DistanceFromRoot : "0",
@@ -32986,36 +33831,43 @@ make root = ${bMakeRoot}`;
32986
33831
  DrillState : "collapsed",
32987
33832
  ID : "3",
32988
33833
  Name : "Gamma*"
32989
- }, {
32990
- DescendantCount : "0",
32991
- DistanceFromRoot : "0",
32992
- DrillState : "leaf",
32993
- ID : "5",
32994
- Name : "Epsilon*"
32995
33834
  }]
32996
33835
  })
32997
33836
  .expectRequest({
32998
- batchNo : 7,
33837
+ batchNo : 9,
32999
33838
  url : sUrlWithExpandLevels
33000
33839
  + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,LimitedRank"
33001
- + "&$filter=ID eq '6' or ID eq '7'&$top=2"
33840
+ + "&$filter=ID eq '1' or ID eq '6' or ID eq '7' or ID eq '8'&$top=4"
33002
33841
  }, {
33003
33842
  value : [{
33843
+ DescendantCount : "1",
33844
+ DistanceFromRoot : "0",
33845
+ DrillState : "expanded",
33846
+ ID : "1",
33847
+ LimitedRank : "0"
33848
+ }, {
33849
+ DescendantCount : "0",
33850
+ DistanceFromRoot : "1",
33851
+ DrillState : "leaf",
33852
+ ID : "8",
33853
+ LimitedRank : "1"
33854
+ }, {
33004
33855
  DescendantCount : "0",
33005
33856
  DistanceFromRoot : "0",
33006
33857
  DrillState : "leaf",
33007
33858
  ID : "6",
33008
- LimitedRank : "4"
33859
+ LimitedRank : "5"
33009
33860
  }, {
33010
33861
  DescendantCount : "0",
33011
33862
  DistanceFromRoot : "0",
33012
33863
  DrillState : "leaf",
33013
33864
  ID : "7",
33014
- LimitedRank : "5"
33865
+ LimitedRank : "6"
33015
33866
  }]
33016
33867
  })
33017
33868
  .expectRequest({
33018
- batchNo : 7,
33869
+ batchNo : 9,
33870
+ // Important: this request contains no Levels=2 and no ExpandLevels
33019
33871
  url : "EMPLOYEES?custom=foo&$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels"
33020
33872
  + "(HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
33021
33873
  + ",NodeProperty='ID',Levels=1)"
@@ -33026,6 +33878,17 @@ make root = ${bMakeRoot}`;
33026
33878
  {ID : "6", Name : "Zeta*"},
33027
33879
  {ID : "7", Name : "Eta*"}
33028
33880
  ]
33881
+ })
33882
+ .expectRequest({
33883
+ batchNo : 9,
33884
+ // Important: this request contains no Levels=2 and no ExpandLevels
33885
+ url : "EMPLOYEES?custom=foo&$apply=descendants($root/EMPLOYEES"
33886
+ + ",OrgChart,ID,filter(ID eq '1'),1)"
33887
+ + "&$select=ID,Name"
33888
+ + "&$filter=ID eq '8'"
33889
+ + "&$top=1"
33890
+ }, {
33891
+ value : [{ID : "8", Name : "Theta*"}]
33029
33892
  });
33030
33893
 
33031
33894
  await Promise.all([
@@ -33037,29 +33900,367 @@ make root = ${bMakeRoot}`;
33037
33900
  "/EMPLOYEES('7')",
33038
33901
  "/EMPLOYEES('6')",
33039
33902
  "/EMPLOYEES('1')",
33903
+ "/EMPLOYEES('8')",
33040
33904
  "/EMPLOYEES('2')",
33041
- "/EMPLOYEES('3')",
33042
- "/EMPLOYEES('5')"
33905
+ "/EMPLOYEES('3')"
33043
33906
  ], [
33044
- [undefined, 1, "Alpha*"],
33045
- [undefined, 1, "Beta*"]
33046
- ]);
33907
+ [true, 1, "Alpha*"],
33908
+ [undefined, 2, "Theta*"]
33909
+ ], 7);
33910
+
33911
+ this.expectRequest(sUrlWithExpandLevels
33912
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,Name"
33913
+ + "&$skip=4&$top=1", {
33914
+ value : [{
33915
+ DescendantCount : "0",
33916
+ DistanceFromRoot : "0",
33917
+ DrillState : "leaf",
33918
+ ID : "5",
33919
+ Name : "Epsilon*"
33920
+ }]
33921
+ });
33047
33922
 
33048
33923
  await this.checkAllContexts("(4) check all contexts", assert, oBinding,
33049
33924
  ["@$ui5.node.isExpanded", "@$ui5.node.level", "Name"], [
33050
33925
  [undefined, 1, "Eta*"],
33051
33926
  [undefined, 1, "Zeta*"],
33052
- [undefined, 1, "Alpha*"],
33927
+ [true, 1, "Alpha*"],
33928
+ [undefined, 2, "Theta*"],
33053
33929
  [undefined, 1, "Beta*"],
33054
33930
  [false, 1, "Gamma*"],
33055
33931
  [undefined, 1, "Epsilon*"]
33056
33932
  ]);
33057
33933
  });
33058
33934
 
33935
+ //*********************************************************************************************
33936
+ // Scenario: A hierarchy has two visible rows and is completely expanded.
33937
+ // (1) Create New1 below Alpha; create New2 below New1
33938
+ // (2) Side-effects refresh (delivers new nested "bonus items" below New1)
33939
+ // (3) Check all contexts
33940
+ // (4) Collapse Alpha
33941
+ // (5) Side-effects refresh
33942
+ // (6) Expand Alpha (restores out-of-place positions)
33943
+ // (7) Check all contexts
33944
+ // JIRA: CPOUI5ODATAV4-2510
33945
+ QUnit.test("Recursive Hierarchy: out of place, bonus item, collapse", async function (assert) {
33946
+ const oModel = this.createTeaBusiModel({autoExpandSelect : true});
33947
+ const sUrl = "EMPLOYEES"
33948
+ + "?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root/EMPLOYEES"
33949
+ + ",HierarchyQualifier='OrgChart',NodeProperty='ID')";
33950
+ const sUrlWithExpandLevels = sUrl.slice(0, -1)
33951
+ + ",ExpandLevels=" + JSON.stringify([{NodeID : "11", Levels : 1}]) + ")";
33952
+ const sUrlWithExpandLevelsCollapsed = sUrl.slice(0, -1) + ",ExpandLevels="
33953
+ + JSON.stringify([{NodeID : "11", Levels : 1}, {NodeID : "1", Levels : 0}]) + ")";
33954
+ const sView = `
33955
+ <t:Table id="table" rows="{path : '/EMPLOYEES',
33956
+ parameters : {
33957
+ $$aggregation : {
33958
+ expandTo : 1E16,
33959
+ hierarchyQualifier : 'OrgChart'
33960
+ }
33961
+ }}" threshold="0" visibleRowCount="2">
33962
+ <Text text="{= %{@$ui5.node.isExpanded} }"/>
33963
+ <Text text="{= %{@$ui5.node.level} }"/>
33964
+ <Text text="{Name}"/>
33965
+ </t:Table>`;
33966
+
33967
+ // 1 Alpha
33968
+ // 2 Beta
33969
+ // 11 New1 (created)
33970
+ // 21 NewFromServer1 ("bonus item")
33971
+ // 22 NewFromServer2 ("bonus item")
33972
+ // 12 New2 (created)
33973
+ // 3 Gamma
33974
+ this.expectRequest(sUrl
33975
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,Name"
33976
+ + "&$count=true&$skip=0&$top=2", {
33977
+ "@odata.count" : "3",
33978
+ value : [{
33979
+ DescendantCount : "1",
33980
+ DistanceFromRoot : "0",
33981
+ DrillState : "expanded",
33982
+ ID : "1",
33983
+ Name : "Alpha"
33984
+ }, {
33985
+ DescendantCount : "0",
33986
+ DistanceFromRoot : "1",
33987
+ DrillState : "leaf",
33988
+ ID : "2",
33989
+ Name : "Beta"
33990
+ }]
33991
+ });
33992
+
33993
+ await this.createView(assert, sView, oModel);
33994
+
33995
+ const oTable = this.oView.byId("table");
33996
+ const oBinding = oTable.getBinding("rows");
33997
+ checkTable("initial page", assert, oTable, [
33998
+ "/EMPLOYEES('1')",
33999
+ "/EMPLOYEES('2')"
34000
+ ], [
34001
+ [true, 1, "Alpha"],
34002
+ [undefined, 2, "Beta"]
34003
+ ], 3);
34004
+ const oAlpha = oBinding.getCurrentContexts()[0];
34005
+
34006
+ this.expectRequest({
34007
+ method : "POST",
34008
+ url : "EMPLOYEES",
34009
+ payload : {
34010
+ "EMPLOYEE_2_MANAGER@odata.bind" : "EMPLOYEES('1')",
34011
+ Name : "New1"
34012
+ }
34013
+ }, {
34014
+ ID : "11",
34015
+ Name : "New1"
34016
+ })
34017
+ .expectRequest(sUrl + "&$filter=ID eq '11'&$select=LimitedRank", {
34018
+ value : [{
34019
+ LimitedRank : "2"
34020
+ }]
34021
+ });
34022
+
34023
+ const oNew1 = oBinding.create({
34024
+ "@$ui5.node.parent" : oAlpha,
34025
+ Name : "New1"
34026
+ }, /*bSkipRefresh*/true);
34027
+
34028
+ await Promise.all([
34029
+ oNew1.created(),
34030
+ this.waitForChanges(assert, "(1) create New1")
34031
+ ]);
34032
+
34033
+ this.expectRequest({
34034
+ method : "POST",
34035
+ url : "EMPLOYEES",
34036
+ payload : {
34037
+ "EMPLOYEE_2_MANAGER@odata.bind" : "EMPLOYEES('11')",
34038
+ Name : "New2"
34039
+ }
34040
+ }, {
34041
+ ID : "12",
34042
+ Name : "New2"
34043
+ })
34044
+ .expectRequest(sUrl + "&$filter=ID eq '12'&$select=LimitedRank", {
34045
+ value : [{
34046
+ LimitedRank : "3"
34047
+ }]
34048
+ });
34049
+
34050
+ const oNew2 = oBinding.create({
34051
+ "@$ui5.node.parent" : oNew1,
34052
+ Name : "New2"
34053
+ }, /*bSkipRefresh*/true);
34054
+
34055
+ await Promise.all([
34056
+ oNew2.created(),
34057
+ this.waitForChanges(assert, "(1) create New2")
34058
+ ]);
34059
+
34060
+ checkTable("after (1)", assert, oTable, [
34061
+ "/EMPLOYEES('1')",
34062
+ "/EMPLOYEES('11')",
34063
+ "/EMPLOYEES('12')",
34064
+ "/EMPLOYEES('2')"
34065
+ ], [
34066
+ [true, 1, "Alpha"],
34067
+ [true, 2, "New1"]
34068
+ ], 5);
34069
+
34070
+ const expectSideEffectsRequests = () => {
34071
+ this.expectRequest(sUrlWithExpandLevels
34072
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,Name"
34073
+ + "&$count=true&$skip=0&$top=2", {
34074
+ "@odata.count" : "7",
34075
+ value : [{
34076
+ DescendantCount : "5",
34077
+ DistanceFromRoot : "0",
34078
+ DrillState : "expanded",
34079
+ ID : "1",
34080
+ Name : "Alpha*"
34081
+ }, {
34082
+ DescendantCount : "0",
34083
+ DistanceFromRoot : "1",
34084
+ DrillState : "leaf",
34085
+ ID : "2",
34086
+ Name : "Beta*"
34087
+ }]
34088
+ })
34089
+ .expectRequest(sUrlWithExpandLevels
34090
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,LimitedRank"
34091
+ + "&$filter=ID eq '1' or ID eq '11' or ID eq '12'&$top=3", {
34092
+ value : [{
34093
+ DescendantCount : "5",
34094
+ DistanceFromRoot : "0",
34095
+ DrillState : "expanded",
34096
+ ID : "1",
34097
+ LimitedRank : "0"
34098
+ }, {
34099
+ DescendantCount : "3",
34100
+ DistanceFromRoot : "1",
34101
+ DrillState : "expanded",
34102
+ ID : "11",
34103
+ LimitedRank : "2"
34104
+ }, {
34105
+ DescendantCount : "0",
34106
+ DistanceFromRoot : "2",
34107
+ DrillState : "leaf",
34108
+ ID : "12",
34109
+ LimitedRank : "5"
34110
+ }]
34111
+ })
34112
+ .expectRequest("EMPLOYEES"
34113
+ + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '1'),1)"
34114
+ + "&$select=ID,Name&$filter=ID eq '11'&$top=1", {
34115
+ value : [
34116
+ {ID : "11", Name : "New1*"}
34117
+ ]
34118
+ })
34119
+ .expectRequest("EMPLOYEES"
34120
+ + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '11'),1)"
34121
+ + "&$select=ID,Name&$filter=ID eq '12'&$top=1", {
34122
+ value : [
34123
+ {ID : "12", Name : "New2*"}
34124
+ ]
34125
+ });
34126
+ };
34127
+
34128
+ expectSideEffectsRequests();
34129
+
34130
+ await Promise.all([
34131
+ // code under test
34132
+ oBinding.getHeaderContext().requestSideEffects([""]),
34133
+ this.waitForChanges(assert, "(2) side-effects refresh")
34134
+ ]);
34135
+
34136
+ const checkAllContexts = async (iStep) => {
34137
+ this.expectRequest(sUrlWithExpandLevels
34138
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,Name"
34139
+ + "&$skip=3&$top=2", {
34140
+ value : [{
34141
+ DescendantCount : "1",
34142
+ DistanceFromRoot : "2",
34143
+ DrillState : "expanded",
34144
+ ID : "21",
34145
+ Name : "NewFromServer1*"
34146
+ }, {
34147
+ DescendantCount : "0",
34148
+ DistanceFromRoot : "3",
34149
+ DrillState : "leaf",
34150
+ ID : "22",
34151
+ Name : "NewFromServer2*"
34152
+ }]
34153
+ })
34154
+ .expectRequest(sUrlWithExpandLevels
34155
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,Name"
34156
+ + "&$skip=6&$top=1", {
34157
+ value : [{
34158
+ DescendantCount : "0",
34159
+ DistanceFromRoot : "0",
34160
+ DrillState : "leaf",
34161
+ ID : "3",
34162
+ Name : "Gamma*"
34163
+ }]
34164
+ });
34165
+
34166
+ await this.checkAllContexts(`(${iStep}) check all contexts`, assert, oBinding,
34167
+ ["@$ui5.node.isExpanded", "@$ui5.node.level", "Name"], [
34168
+ [true, 1, "Alpha*"],
34169
+ [true, 2, "New1*"],
34170
+ [undefined, 3, "New2*"],
34171
+ [true, 3, "NewFromServer1*"],
34172
+ [undefined, 4, "NewFromServer2*"],
34173
+ [undefined, 2, "Beta*"],
34174
+ [undefined, 1, "Gamma*"]
34175
+ ]);
34176
+ };
34177
+
34178
+ await checkAllContexts(3);
34179
+
34180
+ oAlpha.collapse();
34181
+
34182
+ await this.waitForChanges(assert, "(4) collapse Alpha");
34183
+
34184
+ checkTable("after (4)", assert, oTable, [
34185
+ "/EMPLOYEES('1')",
34186
+ "/EMPLOYEES('3')"
34187
+ ], [
34188
+ [false, 1, "Alpha*"],
34189
+ [undefined, 1, "Gamma*"]
34190
+ ]);
34191
+
34192
+ this.expectRequest(sUrlWithExpandLevelsCollapsed
34193
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,Name"
34194
+ + "&$count=true&$skip=0&$top=2", {
34195
+ "@odata.count" : "2",
34196
+ value : [{
34197
+ DescendantCount : "0",
34198
+ DistanceFromRoot : "0",
34199
+ DrillState : "collapsed",
34200
+ ID : "1",
34201
+ Name : "Alpha*"
34202
+ }, {
34203
+ DescendantCount : "0",
34204
+ DistanceFromRoot : "0",
34205
+ DrillState : "leaf",
34206
+ ID : "3",
34207
+ Name : "Gamma*"
34208
+ }]
34209
+ })
34210
+ .expectRequest(sUrlWithExpandLevelsCollapsed
34211
+ + "&$select=DescendantCount,DistanceFromRoot,DrillState,ID,LimitedRank"
34212
+ + "&$filter=ID eq '1' or ID eq '11' or ID eq '12'&$top=3", {
34213
+ value : [{
34214
+ DescendantCount : "0",
34215
+ DistanceFromRoot : "0",
34216
+ DrillState : "collapsed",
34217
+ ID : "1",
34218
+ LimitedRank : "0"
34219
+ }]
34220
+ })
34221
+ .expectRequest("EMPLOYEES"
34222
+ + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '1'),1)"
34223
+ + "&$select=ID,Name&$filter=ID eq '11'&$top=1", {
34224
+ value : [
34225
+ {ID : "11", Name : "New1*"}
34226
+ ]
34227
+ })
34228
+ .expectRequest("EMPLOYEES"
34229
+ + "?$apply=descendants($root/EMPLOYEES,OrgChart,ID,filter(ID eq '11'),1)"
34230
+ + "&$select=ID,Name&$filter=ID eq '12'&$top=1", {
34231
+ value : [
34232
+ {ID : "12", Name : "New2*"}
34233
+ ]
34234
+ });
34235
+
34236
+ await Promise.all([
34237
+ // code under test
34238
+ oBinding.getHeaderContext().requestSideEffects([""]),
34239
+ this.waitForChanges(assert, "(5) side-effects refresh")
34240
+ ]);
34241
+
34242
+ checkTable("after (5)", assert, oTable, [
34243
+ "/EMPLOYEES('1')",
34244
+ "/EMPLOYEES('3')"
34245
+ ], [
34246
+ [false, 1, "Alpha*"],
34247
+ [undefined, 1, "Gamma*"]
34248
+ ]);
34249
+
34250
+ expectSideEffectsRequests();
34251
+
34252
+ // code under test
34253
+ oAlpha.expand();
34254
+
34255
+ await this.waitForChanges(assert, "(6) expand Alpha");
34256
+
34257
+ await checkAllContexts(7);
34258
+ });
34259
+
33059
34260
  //*********************************************************************************************
33060
34261
  // Scenario: Expand all levels of a recursive hierarchy and move a node with descendants (not
33061
- // yet fully loaded) to another parent. Although it is shown as the new parent's first child on
33062
- // UI, it is actually inserted between older siblings on the server. Still, paging works!
34262
+ // yet fully loaded) to another parent. It is inserted between older siblings on the server and
34263
+ // is shown on the client "in place" (JIRA: CPOUI5ODATAV4-2466). Still, paging works!
33063
34264
  // Collapse the new parent and later its root to check that their "descendants" is correct.
33064
34265
  // A new root (Beth) is created with a new child (Gimel) and moved to Aleph, but their
33065
34266
  // LimitedRank does not change. Then Gimel is moved to Aleph, thus Beth becomes a leaf again.
@@ -33221,8 +34422,8 @@ make root = ${bMakeRoot}`;
33221
34422
  // 3.1 Theta
33222
34423
  // 3.2 Iota
33223
34424
  // 1 Beta (moved...)
33224
- // 1.1 Gamma
33225
- // 1.1.1 Delta (loaded later)
34425
+ // 1.1 Gamma <-- first visible row
34426
+ // 1.1.1 Delta (loaded soon)
33226
34427
  // 1.1.2 Epsilon (loaded soon)
33227
34428
  // 3.3 Kappa (loaded later)
33228
34429
  // 4 Lambda (loaded later)
@@ -33251,9 +34452,19 @@ make root = ${bMakeRoot}`;
33251
34452
  })
33252
34453
  .expectRequest({
33253
34454
  batchNo : 4,
33254
- url : sReadUrl + "&$skip=8&$top=1"
34455
+ url : sReadUrl + "&$skip=7&$top=2"
33255
34456
  }, {
33256
34457
  value : [{
34458
+ ArtistID : "1.1.1",
34459
+ IsActiveEntity : false,
34460
+ Name : "Delta",
34461
+ _ : {
34462
+ DescendantCount : "0",
34463
+ DistanceFromRoot : "4",
34464
+ DrillState : "leaf",
34465
+ NodeID : "1.1.1,false"
34466
+ }
34467
+ }, {
33257
34468
  ArtistID : "1.1.2",
33258
34469
  IsActiveEntity : false,
33259
34470
  Name : "Epsilon",
@@ -33276,15 +34487,16 @@ make root = ${bMakeRoot}`;
33276
34487
  checkTable("after move", assert, oTable, [
33277
34488
  sFriend + "(ArtistID='0',IsActiveEntity=false)",
33278
34489
  sFriend + "(ArtistID='3',IsActiveEntity=false)",
34490
+ sFriend + "(ArtistID='3.1',IsActiveEntity=false)",
34491
+ sFriend + "(ArtistID='3.2',IsActiveEntity=false)",
33279
34492
  sFriend + "(ArtistID='1',IsActiveEntity=false)",
33280
34493
  sFriend + "(ArtistID='1.1',IsActiveEntity=false)",
33281
- sFriend + "(ArtistID='1.1.2',IsActiveEntity=false)",
33282
- sFriend + "(ArtistID='3.1',IsActiveEntity=false)",
33283
- sFriend + "(ArtistID='3.2',IsActiveEntity=false)"
34494
+ sFriend + "(ArtistID='1.1.1',IsActiveEntity=false)",
34495
+ sFriend + "(ArtistID='1.1.2',IsActiveEntity=false)"
33284
34496
  ], [
33285
- [undefined, 5, "1.1.2", "Epsilon"],
33286
- [undefined, 3, "3.1", "Theta"], // Note: on UI, Beta is shown as 1st child of Eta!
33287
- [undefined, 3, "3.2", "Iota"]
34497
+ [true, 4, "1.1", "Gamma"],
34498
+ [undefined, 5, "1.1.1", "Delta"],
34499
+ [undefined, 5, "1.1.2", "Epsilon"]
33288
34500
  ], 12);
33289
34501
 
33290
34502
  assert.strictEqual(oBeta.isTransient(), undefined, "unchanged");
@@ -33315,19 +34527,6 @@ make root = ${bMakeRoot}`;
33315
34527
  }
33316
34528
  }]
33317
34529
  })
33318
- .expectRequest(sReadUrl + "&$skip=7&$top=1", {
33319
- value : [{
33320
- ArtistID : "1.1.1",
33321
- IsActiveEntity : false,
33322
- Name : "Delta",
33323
- _ : {
33324
- DescendantCount : "0",
33325
- DistanceFromRoot : "4",
33326
- DrillState : "leaf",
33327
- NodeID : "1.1.1,false"
33328
- }
33329
- }]
33330
- })
33331
34530
  .expectRequest(sReadUrl + "&$skip=9&$top=3", {
33332
34531
  value : [{
33333
34532
  ArtistID : "3.3",
@@ -33367,12 +34566,12 @@ make root = ${bMakeRoot}`;
33367
34566
  [true, 1, "0", "Alpha"],
33368
34567
  [undefined, 2, "2", "Zeta"],
33369
34568
  [true, 2, "3", "Eta"],
34569
+ [undefined, 3, "3.1", "Theta"],
34570
+ [undefined, 3, "3.2", "Iota"],
33370
34571
  [true, 3, "1", "Beta"],
33371
34572
  [true, 4, "1.1", "Gamma"],
33372
34573
  [undefined, 5, "1.1.1", "Delta"],
33373
34574
  [undefined, 5, "1.1.2", "Epsilon"],
33374
- [undefined, 3, "3.1", "Theta"], // Note: on UI, Beta is shown as 1st child of Eta!
33375
- [undefined, 3, "3.2", "Iota"],
33376
34575
  [undefined, 3, "3.3", "Kappa"],
33377
34576
  [undefined, 2, "4", "Lambda"],
33378
34577
  [undefined, 1, "9", "Aleph"]
@@ -33428,11 +34627,27 @@ make root = ${bMakeRoot}`;
33428
34627
  Name : "Beth",
33429
34628
  _ : null // not available w/ RAP for a non-hierarchical request
33430
34629
  })
33431
- .expectRequest(sBaseUrl + "&$filter=ArtistID eq '10' and IsActiveEntity eq false"
33432
- + "&$select=_/" + sLimitedRank + ",_/NodeID", {
34630
+ .expectRequest({
34631
+ batchNo : 7,
34632
+ url : sBaseUrl + "&$filter=ArtistID eq '10' and IsActiveEntity eq false"
34633
+ + "&$select=_/" + sLimitedRank
34634
+ }, {
34635
+ value : [{
34636
+ _ : {
34637
+ [sLimitedRank] : "12" // Edm.Int64
34638
+ }
34639
+ }]
34640
+ })
34641
+ .expectRequest({
34642
+ batchNo : 7,
34643
+ // no "orderby(...)" due to SNOW: DINC0087713
34644
+ url : sFriend.slice(1) + "?$apply="
34645
+ + "com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root" + sFriend
34646
+ + ",HierarchyQualifier='" + sHierarchyQualifier + "',NodeProperty='_/NodeID')"
34647
+ + "&$filter=ArtistID eq '10' and IsActiveEntity eq false&$select=_/NodeID"
34648
+ }, {
33433
34649
  value : [{
33434
34650
  _ : {
33435
- [sLimitedRank] : "12", // Edm.Int64
33436
34651
  NodeID : "10,false"
33437
34652
  }
33438
34653
  }]
@@ -33452,6 +34667,7 @@ make root = ${bMakeRoot}`;
33452
34667
  ]);
33453
34668
 
33454
34669
  assert.deepEqual(oBeth.getObject("_"), {NodeID : "10,false"});
34670
+ checkCreatedPersisted(assert, oBeth, oBethCreated);
33455
34671
 
33456
34672
  await this.checkAllContexts("after create new root Beth", assert, oListBinding,
33457
34673
  ["@$ui5.node.isExpanded", "@$ui5.node.level", "ArtistID", "Name"], [
@@ -33461,7 +34677,6 @@ make root = ${bMakeRoot}`;
33461
34677
  ]);
33462
34678
 
33463
34679
  const oAleph = oTable.getRows()[2].getBindingContext();
33464
- checkCreatedPersisted(assert, oBeth, oBethCreated);
33465
34680
 
33466
34681
  this.expectRequest({
33467
34682
  method : "POST",
@@ -33476,11 +34691,27 @@ make root = ${bMakeRoot}`;
33476
34691
  Name : "Gimel",
33477
34692
  _ : null // not available w/ RAP for a non-hierarchical request
33478
34693
  })
33479
- .expectRequest(sBaseUrl + "&$filter=ArtistID eq '10.1' and IsActiveEntity eq false"
33480
- + "&$select=_/" + sLimitedRank + ",_/NodeID", {
34694
+ .expectRequest({
34695
+ batchNo : 9,
34696
+ url : sBaseUrl + "&$filter=ArtistID eq '10.1' and IsActiveEntity eq false"
34697
+ + "&$select=_/" + sLimitedRank
34698
+ }, {
34699
+ value : [{
34700
+ _ : {
34701
+ [sLimitedRank] : "13" // Edm.Int64
34702
+ }
34703
+ }]
34704
+ })
34705
+ .expectRequest({
34706
+ batchNo : 9,
34707
+ // no "orderby(...)" due to SNOW: DINC0087713
34708
+ url : sFriend.slice(1) + "?$apply="
34709
+ + "com.sap.vocabularies.Hierarchy.v1.TopLevels(HierarchyNodes=$root" + sFriend
34710
+ + ",HierarchyQualifier='" + sHierarchyQualifier + "',NodeProperty='_/NodeID')"
34711
+ + "&$filter=ArtistID eq '10.1' and IsActiveEntity eq false&$select=_/NodeID"
34712
+ }, {
33481
34713
  value : [{
33482
34714
  _ : {
33483
- [sLimitedRank] : "13", // Edm.Int64
33484
34715
  NodeID : "10.1,false"
33485
34716
  }
33486
34717
  }]
@@ -33502,6 +34733,7 @@ make root = ${bMakeRoot}`;
33502
34733
  ]);
33503
34734
 
33504
34735
  assert.deepEqual(oGimel.getObject("_"), {NodeID : "10.1,false"});
34736
+ checkCreatedPersisted(assert, oGimel, oGimelCreated);
33505
34737
 
33506
34738
  await this.checkAllContexts("after create new child Gimel", assert, oListBinding,
33507
34739
  ["@$ui5.node.isExpanded", "@$ui5.node.level", "ArtistID", "Name"], [
@@ -33511,8 +34743,6 @@ make root = ${bMakeRoot}`;
33511
34743
  [undefined, 1, "9", "Aleph"]
33512
34744
  ]);
33513
34745
 
33514
- checkCreatedPersisted(assert, oGimel, oGimelCreated);
33515
-
33516
34746
  // 0 Alpha
33517
34747
  // 2 Zeta
33518
34748
  // 3 Eta
@@ -33556,6 +34786,9 @@ make root = ${bMakeRoot}`;
33556
34786
  this.waitForChanges(assert, "move Beth to Aleph")
33557
34787
  ]);
33558
34788
 
34789
+ checkPersisted(assert, oBeth);
34790
+ checkCreatedPersisted(assert, oGimel, oGimelCreated);
34791
+
33559
34792
  // Note: #checkAllContexts will check #getIndex for all nodes
33560
34793
  await this.checkAllContexts("after move Beth to Aleph", assert, oListBinding,
33561
34794
  ["@$ui5.node.isExpanded", "@$ui5.node.level", "ArtistID", "Name"], [
@@ -33565,9 +34798,6 @@ make root = ${bMakeRoot}`;
33565
34798
  [undefined, 3, "10.1", "Gimel"]
33566
34799
  ]);
33567
34800
 
33568
- checkCreatedPersisted(assert, oBeth, oBethCreated);
33569
- checkCreatedPersisted(assert, oGimel, oGimelCreated);
33570
-
33571
34801
  this.expectRequest({
33572
34802
  batchNo : 11,
33573
34803
  headers : {
@@ -33597,20 +34827,18 @@ make root = ${bMakeRoot}`;
33597
34827
  this.waitForChanges(assert, "move Gimel to Aleph")
33598
34828
  ]);
33599
34829
 
34830
+ checkPersisted(assert, oGimel);
34831
+
33600
34832
  // Note: #checkAllContexts will check #getIndex for all nodes
33601
34833
  await this.checkAllContexts("after move Gimel to Aleph", assert, oListBinding,
33602
34834
  ["@$ui5.node.isExpanded", "@$ui5.node.level", "ArtistID", "Name"], [
33603
34835
  [false, 1, "0", "Alpha"],
33604
34836
  [true, 1, "9", "Aleph"],
33605
- [undefined, 2, "10.1", "Gimel"],
33606
- [undefined, 2, "10", "Beth"] // last child has gone
34837
+ [undefined, 2, "10", "Beth"], // last child has gone
34838
+ [undefined, 2, "10.1", "Gimel"]
33607
34839
  ]);
33608
34840
 
33609
- checkCreatedPersisted(assert, oBeth, oBethCreated);
33610
- checkCreatedPersisted(assert, oGimel, oGimelCreated);
33611
-
33612
34841
  // 0 Alpha
33613
- // 10.1 Gimel (moved to here)
33614
34842
  // 2 Zeta
33615
34843
  // 3 Eta (still collapsed)
33616
34844
  // 3.1 Theta
@@ -33620,6 +34848,7 @@ make root = ${bMakeRoot}`;
33620
34848
  // 1.1.1 Delta
33621
34849
  // 1.1.2 Epsilon
33622
34850
  // 3.3 Kappa
34851
+ // 10.1 Gimel (moved to here)
33623
34852
  // 4 Lambda
33624
34853
  // 9 Aleph
33625
34854
  // 10 Beth
@@ -33640,8 +34869,8 @@ make root = ${bMakeRoot}`;
33640
34869
  + "&$select=_/" + sLimitedRank
33641
34870
  }, {
33642
34871
  value : [{
33643
- _ : { // Note: same rank on UI as on server
33644
- [sLimitedRank] : "1" // Edm.Int64
34872
+ _ : {
34873
+ [sLimitedRank] : "10" // Edm.Int64
33645
34874
  }
33646
34875
  }]
33647
34876
  });
@@ -33656,15 +34885,16 @@ make root = ${bMakeRoot}`;
33656
34885
  await this.checkAllContexts("after move Gimel to collapsed Alpha", assert, oListBinding,
33657
34886
  ["@$ui5.node.isExpanded", "@$ui5.node.level", "ArtistID", "Name"], [
33658
34887
  [true, 1, "0", "Alpha"], // auto-expanded
33659
- [undefined, 2, "10.1", "Gimel"],
33660
34888
  [undefined, 2, "2", "Zeta"],
33661
34889
  [false, 2, "3", "Eta"], // still collapsed
34890
+ [undefined, 2, "10.1", "Gimel"],
33662
34891
  [undefined, 2, "4", "Lambda"],
33663
34892
  [true, 1, "9", "Aleph"],
33664
34893
  [undefined, 2, "10", "Beth"]
33665
34894
  ]);
33666
34895
 
33667
- oEta = oListBinding.getAllCurrentContexts()[3];
34896
+ oEta = oListBinding.getAllCurrentContexts()[2];
34897
+ assert.strictEqual(oEta.getProperty("Name"), "Eta", "double check that index was right");
33668
34898
 
33669
34899
  // code under test
33670
34900
  oEta.expand();
@@ -33672,22 +34902,23 @@ make root = ${bMakeRoot}`;
33672
34902
  await this.checkAllContexts("after expand all again", assert, oListBinding,
33673
34903
  ["@$ui5.node.isExpanded", "@$ui5.node.level", "ArtistID", "Name"], [
33674
34904
  [true, 1, "0", "Alpha"],
33675
- [undefined, 2, "10.1", "Gimel"],
33676
34905
  [undefined, 2, "2", "Zeta"],
33677
34906
  [true, 2, "3", "Eta"],
34907
+ [undefined, 3, "3.1", "Theta"],
34908
+ [undefined, 3, "3.2", "Iota"],
33678
34909
  [true, 3, "1", "Beta"],
33679
34910
  [true, 4, "1.1", "Gamma"],
33680
34911
  [undefined, 5, "1.1.1", "Delta"],
33681
34912
  [undefined, 5, "1.1.2", "Epsilon"],
33682
- [undefined, 3, "3.1", "Theta"],
33683
- [undefined, 3, "3.2", "Iota"],
33684
34913
  [undefined, 3, "3.3", "Kappa"],
34914
+ [undefined, 2, "10.1", "Gimel"],
33685
34915
  [undefined, 2, "4", "Lambda"],
33686
34916
  [true, 1, "9", "Aleph"],
33687
34917
  [undefined, 2, "10", "Beth"]
33688
34918
  ]);
33689
34919
 
33690
- oBeta = oListBinding.getAllCurrentContexts()[4];
34920
+ oBeta = oListBinding.getAllCurrentContexts()[5];
34921
+ assert.strictEqual(oBeta.getProperty("Name"), "Beta", "double check that index was right");
33691
34922
 
33692
34923
  if (bMakeRoot) {
33693
34924
  this.expectRequest({
@@ -33727,12 +34958,12 @@ make root = ${bMakeRoot}`;
33727
34958
  [undefined, 3, "1.1.1", "Delta"],
33728
34959
  [undefined, 3, "1.1.2", "Epsilon"],
33729
34960
  [true, 1, "0", "Alpha"],
33730
- [undefined, 2, "10.1", "Gimel"],
33731
34961
  [undefined, 2, "2", "Zeta"],
33732
34962
  [true, 2, "3", "Eta"],
33733
34963
  [undefined, 3, "3.1", "Theta"],
33734
34964
  [undefined, 3, "3.2", "Iota"],
33735
34965
  [undefined, 3, "3.3", "Kappa"],
34966
+ [undefined, 2, "10.1", "Gimel"],
33736
34967
  [undefined, 2, "4", "Lambda"],
33737
34968
  [true, 1, "9", "Aleph"],
33738
34969
  [undefined, 2, "10", "Beth"]
@@ -33973,13 +35204,14 @@ make root = ${bMakeRoot}`;
33973
35204
  QUnit.test("Recursive Hierarchy: #requestParent for non-adjacent children",
33974
35205
  async function (assert) {
33975
35206
  const oModel = this.createTeaBusiModel({autoExpandSelect : true});
33976
- const sUrl = "EMPLOYEES?$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
35207
+ const sUrl = "EMPLOYEES?custom=foo&$apply=com.sap.vocabularies.Hierarchy.v1.TopLevels("
33977
35208
  + "HierarchyNodes=$root/EMPLOYEES,HierarchyQualifier='OrgChart'"
33978
35209
  + ",NodeProperty='ID',Levels=2)";
33979
35210
  const sView = `
33980
35211
  <t:Table id="table" rows="{path : '/EMPLOYEES',
33981
35212
  parameters : {
33982
- $$aggregation : {expandTo : 2, hierarchyQualifier : 'OrgChart'}
35213
+ $$aggregation : {expandTo : 2, hierarchyQualifier : 'OrgChart'},
35214
+ custom : 'foo'
33983
35215
  }}" firstVisibleRow="2" threshold="0" visibleRowCount="2">
33984
35216
  <Text text="{= %{@$ui5.node.isExpanded} }"/>
33985
35217
  <Text text="{= %{@$ui5.node.level} }"/>
@@ -34061,7 +35293,8 @@ make root = ${bMakeRoot}`;
34061
35293
 
34062
35294
  this.expectRequest({
34063
35295
  batchNo : 3,
34064
- url : "EMPLOYEES?$apply=ancestors($root/EMPLOYEES,OrgChart,ID,filter(ID eq '2'),1)"
35296
+ url : "EMPLOYEES?custom=foo"
35297
+ + "&$apply=ancestors($root/EMPLOYEES,OrgChart,ID,filter(ID eq '2'),1)"
34065
35298
  + "&$select=ID,Name"
34066
35299
  }, {
34067
35300
  value : [{
@@ -34071,7 +35304,8 @@ make root = ${bMakeRoot}`;
34071
35304
  })
34072
35305
  .expectRequest({
34073
35306
  batchNo : 3,
34074
- url : "EMPLOYEES?$apply=ancestors($root/EMPLOYEES,OrgChart,ID,filter(ID eq '5'),1)"
35307
+ url : "EMPLOYEES?custom=foo"
35308
+ + "&$apply=ancestors($root/EMPLOYEES,OrgChart,ID,filter(ID eq '5'),1)"
34075
35309
  + "&$select=ID,Name"
34076
35310
  }, {
34077
35311
  value : [{
@@ -34113,7 +35347,8 @@ make root = ${bMakeRoot}`;
34113
35347
  assert.strictEqual(oEta.getParent(), oAlpha);
34114
35348
  assert.strictEqual(oDelta.getParent(), oAlpha);
34115
35349
 
34116
- this.expectRequest("EMPLOYEES?$select=ID,Name&$filter=ID eq '5' or ID eq '6'&$top=2", {
35350
+ this.expectRequest("EMPLOYEES?custom=foo&$select=ID,Name&$filter=ID eq '5' or ID eq '6'"
35351
+ + "&$top=2", {
34117
35352
  value : [{
34118
35353
  DrillState : "leaf",
34119
35354
  ID : "5",
@@ -34186,7 +35421,8 @@ make root = ${bMakeRoot}`;
34186
35421
  ]);
34187
35422
 
34188
35423
  this.expectRequest({
34189
- url : "EMPLOYEES?$apply=ancestors($root/EMPLOYEES,OrgChart,ID,filter(ID eq '5'),1)"
35424
+ url : "EMPLOYEES?custom=foo"
35425
+ + "&$apply=ancestors($root/EMPLOYEES,OrgChart,ID,filter(ID eq '5'),1)"
34190
35426
  + "&$select=ID,Name"
34191
35427
  }, {
34192
35428
  value : [{
@@ -36199,7 +37435,7 @@ make root = ${bMakeRoot}`;
36199
37435
 
36200
37436
  //*********************************************************************************************
36201
37437
  // Scenario: Object page bound to active entity: Call the "Edit" bound action on an active
36202
- // entity which responds with the inactive entity. The execute for the "Edit" operation binding
37438
+ // entity which responds with the inactive entity. The invoke for the "Edit" operation binding
36203
37439
  // resolves with the context for the inactive entity. Data for the inactive entity is displayed
36204
37440
  // when setting this context on the object page. It can be edited and side effects can be
36205
37441
  // requested. The controls on the object page bound to the return value context are cleared when
@@ -36214,7 +37450,7 @@ make root = ${bMakeRoot}`;
36214
37450
  operation : "GetDraft",
36215
37451
  method : "GET"
36216
37452
  }].forEach(function (oFixture, i) {
36217
- QUnit.test("bound operation: execute resolves with V4 context, " + i, function (assert) {
37453
+ QUnit.test("bound operation: invoke resolves with V4 context, " + i, function (assert) {
36218
37454
  var oModel = this.createSpecialCasesModel({autoExpandSelect : true}),
36219
37455
  oOperation,
36220
37456
  sRequestPath = "Artists(ArtistID='42',IsActiveEntity=true)/special.cases."
@@ -36285,7 +37521,7 @@ make root = ${bMakeRoot}`;
36285
37521
 
36286
37522
  // code under test
36287
37523
  return Promise.all([
36288
- oOperation.execute(),
37524
+ oOperation.invoke(),
36289
37525
  that.waitForChanges(assert)
36290
37526
  ]);
36291
37527
  }).then(function (aPromiseResults) {
@@ -36342,7 +37578,7 @@ make root = ${bMakeRoot}`;
36342
37578
 
36343
37579
  //*********************************************************************************************
36344
37580
  // Scenario: Object page bound to active entity: Call the "Edit" bound action on an active
36345
- // entity which responds with the inactive entity. The execute for the "Edit" operation binding
37581
+ // entity which responds with the inactive entity. The invoke for the "Edit" operation binding
36346
37582
  // resolves with the context for the inactive entity. Data for the inactive entity is displayed
36347
37583
  // when setting this context on the object page. Then call the "Activate" bound action to switch
36348
37584
  // back to the active entity. The actions are part of the form.
@@ -36465,7 +37701,7 @@ make root = ${bMakeRoot}`;
36465
37701
 
36466
37702
  // code under test
36467
37703
  return Promise.all([
36468
- oAction.execute(undefined, undefined, undefined, bReplaceWithRVC),
37704
+ oAction.invoke(undefined, undefined, undefined, bReplaceWithRVC),
36469
37705
  that.waitForChanges(assert)
36470
37706
  ]).then(function (aPromiseResults) {
36471
37707
  var oContext = aPromiseResults[0]; // the return value context
@@ -36688,7 +37924,7 @@ make root = ${bMakeRoot}`;
36688
37924
  that = this;
36689
37925
 
36690
37926
  /*
36691
- * Executes the given action (ActivationAction or EditAction) on Artist ID 42.
37927
+ * Invokes the given action (ActivationAction or EditAction) on Artist ID 42.
36692
37928
  * Sets the object page to its return value context and waits for the expected changes.
36693
37929
  *
36694
37930
  * @param {string} sAction - The name of the action
@@ -36720,7 +37956,7 @@ make root = ${bMakeRoot}`;
36720
37956
 
36721
37957
  return Promise.all([
36722
37958
  // code under test
36723
- oAction.execute(),
37959
+ oAction.invoke(),
36724
37960
  that.waitForChanges(assert)
36725
37961
  ]).then(function (aPromiseResults) {
36726
37962
  oReturnValueContext = aPromiseResults[0];
@@ -36941,7 +38177,7 @@ make root = ${bMakeRoot}`;
36941
38177
  Messages : []
36942
38178
  });
36943
38179
 
36944
- return oOperationBinding.execute();
38180
+ return oOperationBinding.invoke();
36945
38181
  }).then(function (oReturnValueContext0) {
36946
38182
  // 2. Bind object page to the return value context of the create action
36947
38183
  oReturnValueContext = oReturnValueContext0;
@@ -37045,7 +38281,7 @@ make root = ${bMakeRoot}`;
37045
38281
 
37046
38282
  return Promise.all([
37047
38283
  // code under test
37048
- oAction.execute(),
38284
+ oAction.invoke(),
37049
38285
  that.waitForChanges(assert)
37050
38286
  ]);
37051
38287
  }).then(function (aPromiseResults) {
@@ -37203,7 +38439,7 @@ make root = ${bMakeRoot}`;
37203
38439
 
37204
38440
  //*********************************************************************************************
37205
38441
  // Scenario: Object page bound to an active entity and its navigation property is $expand'ed via
37206
- // an own request. Trigger "Edit" bound action to start editing using a return value context and
38442
+ // an own request. Invoke "Edit" bound action to start editing using a return value context and
37207
38443
  // modify a property in the entity referenced by the navigation property. Activate the inactive
37208
38444
  // entity via a bound action using another return value context.
37209
38445
  // The elements referenced via the navigation property must not be taken from the cache.
@@ -37279,7 +38515,7 @@ make root = ${bMakeRoot}`;
37279
38515
 
37280
38516
  return Promise.all([
37281
38517
  // code under test
37282
- oOperation.execute(),
38518
+ oOperation.invoke(),
37283
38519
  that.waitForChanges(assert)
37284
38520
  ]);
37285
38521
  }).then(function (aPromiseResults) {
@@ -37346,7 +38582,7 @@ make root = ${bMakeRoot}`;
37346
38582
 
37347
38583
  return Promise.all([
37348
38584
  // code under test
37349
- oOperation.execute(),
38585
+ oOperation.invoke(),
37350
38586
  that.waitForChanges(assert)
37351
38587
  ]);
37352
38588
  }).then(function (aPromiseResults) {
@@ -37486,7 +38722,7 @@ make root = ${bMakeRoot}`;
37486
38722
  //*********************************************************************************************
37487
38723
  // Scenario: Object page bound to active entity with a navigation property $expand'ed via
37488
38724
  // auto-$expand/$select. The "Edit" bound action on the active entity has the binding parameter
37489
- // $$inheritExpandSelect set so that it triggers the POST request with the same $expand and
38725
+ // $$inheritExpandSelect set so that it invokes the POST request with the same $expand and
37490
38726
  // $select parameters used for loading the active entity. This way, all fields in the object
37491
38727
  // page can be populated from the bound action response.
37492
38728
  // Read side effects which include navigation properties while there are pending changes.
@@ -37570,7 +38806,7 @@ make root = ${bMakeRoot}`;
37570
38806
 
37571
38807
  return Promise.all([
37572
38808
  // code under test
37573
- oOperation.execute(),
38809
+ oOperation.invoke(),
37574
38810
  that.waitForChanges(assert)
37575
38811
  ]);
37576
38812
  }).then(function (aPromiseResults) {
@@ -37665,7 +38901,7 @@ make root = ${bMakeRoot}`;
37665
38901
  // no change in messages
37666
38902
 
37667
38903
  return Promise.all([
37668
- oOperation.execute(),
38904
+ oOperation.invoke(),
37669
38905
  that.waitForChanges(assert)
37670
38906
  ]);
37671
38907
  });
@@ -37732,7 +38968,7 @@ make root = ${bMakeRoot}`;
37732
38968
 
37733
38969
  return Promise.all([
37734
38970
  // code under test
37735
- oOperation.execute(undefined, false, null, /*bReplaceWithRVC*/true),
38971
+ oOperation.invoke(undefined, false, null, /*bReplaceWithRVC*/true),
37736
38972
  that.waitForChanges(assert)
37737
38973
  ]);
37738
38974
  }).then(function (aResults) {
@@ -37807,14 +39043,14 @@ make root = ${bMakeRoot}`;
37807
39043
 
37808
39044
  return Promise.all([
37809
39045
  // code under test
37810
- oOperation.execute(),
39046
+ oOperation.invoke(),
37811
39047
  that.waitForChanges(assert)
37812
39048
  ]);
37813
39049
  });
37814
39050
  });
37815
39051
 
37816
39052
  //*********************************************************************************************
37817
- // Scenario: Delete return value context obtained from bound action execute.
39053
+ // Scenario: Delete return value context obtained from bound action invoke.
37818
39054
  // JIRA: CPOUI5UISERVICESV3-1193
37819
39055
  QUnit.test("bound operation: delete return value context", function (assert) {
37820
39056
  var oModel = this.createSpecialCasesModel({autoExpandSelect : true}),
@@ -37860,7 +39096,7 @@ make root = ${bMakeRoot}`;
37860
39096
  return Promise.all([
37861
39097
  that.oModel
37862
39098
  .bindContext("special.cases.EditAction(...)", that.oView.getBindingContext())
37863
- .execute(),
39099
+ .invoke(),
37864
39100
  that.waitForChanges(assert)
37865
39101
  ]);
37866
39102
  }).then(function (aPromiseResults) {
@@ -37886,9 +39122,9 @@ make root = ${bMakeRoot}`;
37886
39122
  });
37887
39123
 
37888
39124
  //*********************************************************************************************
37889
- // Scenario: Execute bound action with context for which no data has been read yet.
39125
+ // Scenario: Invoke bound action with context for which no data has been read yet.
37890
39126
  // CPOUI5ODATAV4-1580: show usage of ODataModel#request+getKeyPredicate
37891
- QUnit.test("bound operation: execute bound action on context w/o read", function (assert) {
39127
+ QUnit.test("bound operation: invoke bound action on context w/o read", function (assert) {
37892
39128
  var oEntity = {IsActiveEntity : true, ArtistID : "4/2"}, // reverse key odering
37893
39129
  oModel = this.createSpecialCasesModel({autoExpandSelect : true}),
37894
39130
  oParentContext,
@@ -37911,7 +39147,7 @@ make root = ${bMakeRoot}`;
37911
39147
 
37912
39148
  return Promise.all([
37913
39149
  // code under test
37914
- oModel.bindContext("special.cases.EditAction(...)", oParentContext).execute(),
39150
+ oModel.bindContext("special.cases.EditAction(...)", oParentContext).invoke(),
37915
39151
  that.waitForChanges(assert)
37916
39152
  ]);
37917
39153
  }).then(function (aPromiseResults) {
@@ -37945,7 +39181,7 @@ make root = ${bMakeRoot}`;
37945
39181
  // JIRA: CPOUI5ODATAV4-1271
37946
39182
  //
37947
39183
  // - An invalid value is entered. Editing is canceled, but the active version is unknown and
37948
- // first needs to be retrieved via execution of "SiblingEntity(...)" navigation propery. The
39184
+ // first needs to be retrieved via invocation of "SiblingEntity(...)" navigation propery. The
37949
39185
  // draft is DELETEd afterwards.
37950
39186
  // JIRA: CPOUI5ODATAV4-1272
37951
39187
  ["EditAction", "GetDraft"].forEach(function (sDraftOperation) {
@@ -38073,7 +39309,7 @@ make root = ${bMakeRoot}`;
38073
39309
 
38074
39310
  return Promise.all([
38075
39311
  // code under test
38076
- oDraftOperation.execute(/*sGroupId*/undefined, /*bIgnoreETag*/false,
39312
+ oDraftOperation.invoke(/*sGroupId*/undefined, /*bIgnoreETag*/false,
38077
39313
  /*fnOnStrictHandlingFailed*/null, /*bReplaceWithRVC*/true),
38078
39314
  that.waitForChanges(assert, sDraftOperation)
38079
39315
  ]);
@@ -38155,7 +39391,7 @@ make root = ${bMakeRoot}`;
38155
39391
  // code under test
38156
39392
  oInactiveArtistContext.setProperty("Name", "Mrs Eliot"),
38157
39393
  // code under test
38158
- oActivationAction.execute(/*sGroupId*/undefined, /*bIgnoreETag*/false,
39394
+ oActivationAction.invoke(/*sGroupId*/undefined, /*bIgnoreETag*/false,
38159
39395
  /*fnOnStrictHandlingFailed*/null, /*bReplaceWithRVC*/true),
38160
39396
  that.waitForChanges(assert, "PATCH Name & POST ActivationAction")
38161
39397
  ]).then(function (aResults) {
@@ -38306,7 +39542,7 @@ make root = ${bMakeRoot}`;
38306
39542
 
38307
39543
  return Promise.all([
38308
39544
  // code under test
38309
- oSiblingEntity.execute("$auto", /*bIgnoreETag*/false,
39545
+ oSiblingEntity.invoke("$auto", /*bIgnoreETag*/false,
38310
39546
  /*fnOnStrictHandlingFailed*/null, /*bReplaceWithRVC*/true),
38311
39547
  that.waitForChanges(assert, "SiblingEntity")
38312
39548
  ]);
@@ -38361,7 +39597,7 @@ make root = ${bMakeRoot}`;
38361
39597
  });
38362
39598
 
38363
39599
  //*********************************************************************************************
38364
- // Scenario: Execute bound action; the parent binding has an empty path, but does not have a
39600
+ // Scenario: Invoke bound action; the parent binding has an empty path, but does not have a
38365
39601
  // cache, so that $$inheritExpandSelect must search the query options in the parent's parent.
38366
39602
  // JIRA: CPOUI5ODATAV4-189
38367
39603
  QUnit.test("bound operation: $$inheritExpandSelect and parent w/o cache #1", function (assert) {
@@ -38401,7 +39637,7 @@ make root = ${bMakeRoot}`;
38401
39637
  });
38402
39638
 
38403
39639
  return Promise.all([
38404
- that.oView.byId("action").getObjectBinding().execute(),
39640
+ that.oView.byId("action").getObjectBinding().invoke(),
38405
39641
  that.waitForChanges(assert)
38406
39642
  ]);
38407
39643
  }).then(function (aResults) {
@@ -38410,7 +39646,7 @@ make root = ${bMakeRoot}`;
38410
39646
  });
38411
39647
 
38412
39648
  //*********************************************************************************************
38413
- // Scenario: Execute bound action; the parent binding has a non-empty path, but does not have a
39649
+ // Scenario: Invoke bound action; the parent binding has a non-empty path, but does not have a
38414
39650
  // cache, so that $$inheritExpandSelect must search the query options in the parent's parent.
38415
39651
  // JIRA: CPOUI5ODATAV4-189
38416
39652
  QUnit.test("bound operation: $$inheritExpandSelect and parent w/o cache #2", function (assert) {
@@ -38479,7 +39715,7 @@ make root = ${bMakeRoot}`;
38479
39715
  }]);
38480
39716
 
38481
39717
  return Promise.all([
38482
- that.oView.byId("action").getObjectBinding().execute(),
39718
+ that.oView.byId("action").getObjectBinding().invoke(),
38483
39719
  that.waitForChanges(assert)
38484
39720
  ]);
38485
39721
  }).then(function ([oReturnValueContext]) {
@@ -38539,7 +39775,7 @@ make root = ${bMakeRoot}`;
38539
39775
 
38540
39776
  return Promise.all([
38541
39777
  // code under test
38542
- oAction.execute(),
39778
+ oAction.invoke(),
38543
39779
  that.waitForChanges(assert)
38544
39780
  ]);
38545
39781
  });
@@ -38608,7 +39844,7 @@ make root = ${bMakeRoot}`;
38608
39844
 
38609
39845
  return Promise.all([
38610
39846
  // code under test
38611
- oAction.execute().then(function (oReturnValueContext) {
39847
+ oAction.invoke().then(function (oReturnValueContext) {
38612
39848
  assert.strictEqual(
38613
39849
  oReturnValueContext.getPath(),
38614
39850
  "/TEAMS('02')/TEAM_2_EMPLOYEES('7')");
@@ -38711,7 +39947,7 @@ make root = ${bMakeRoot}`;
38711
39947
 
38712
39948
  return Promise.all([
38713
39949
  // code under test
38714
- oAction.execute(),
39950
+ oAction.invoke(),
38715
39951
  that.waitForChanges(assert)
38716
39952
  ]);
38717
39953
  }).then(function () {
@@ -38726,7 +39962,7 @@ make root = ${bMakeRoot}`;
38726
39962
 
38727
39963
  return Promise.all([
38728
39964
  // code under test
38729
- oFunction.execute(),
39965
+ oFunction.invoke(),
38730
39966
  that.waitForChanges(assert)
38731
39967
  ]);
38732
39968
  });
@@ -38910,7 +40146,7 @@ make root = ${bMakeRoot}`;
38910
40146
  //*********************************************************************************************
38911
40147
  // Scenario:
38912
40148
  // Two List/Detail binding hierarchies for sales orders and sales order line items. When
38913
- // refreshing a single sales order, line items requests are triggered and messages are updated
40149
+ // refreshing a single sales order, line items requests are invoked and messages are updated
38914
40150
  // only for this single sales order and its dependent sales order line items. For other sales
38915
40151
  // orders and their dependent sales order line items cached data is not discarded and messages
38916
40152
  // are kept untouched. If there are unresolved bindings, their cached data which depends on the
@@ -39134,7 +40370,7 @@ make root = ${bMakeRoot}`;
39134
40370
  "None", "");
39135
40371
  }).then(function () {
39136
40372
  // select the first sales order to get its items and messages, request is
39137
- // triggered because the cache for the sales order line items is discarded
40373
+ // invoked because the cache for the sales order line items is discarded
39138
40374
  that.expectRequest("SalesOrderList('0500000347')/SO_2_SOITEM"
39139
40375
  + "?$select=ItemPosition,Messages,Note,SalesOrderID&$skip=0&$top=100", {
39140
40376
  value : [{
@@ -39830,7 +41066,7 @@ make root = ${bMakeRoot}`;
39830
41066
  }]
39831
41067
  }
39832
41068
  })
39833
- .expectChange("name", "") // triggered by setValue
41069
+ .expectChange("name", "") // invoked by setValue
39834
41070
  .expectMessages([{
39835
41071
  code : "1",
39836
41072
  message : "Enter a name",
@@ -39857,7 +41093,7 @@ make root = ${bMakeRoot}`;
39857
41093
  Name : "Hugo",
39858
41094
  __CT__FAKE__Message : {__FAKE__Messages : []}
39859
41095
  })
39860
- .expectChange("name", "Hugo") // triggered by setValue
41096
+ .expectChange("name", "Hugo") // invoked by setValue
39861
41097
  .expectMessages([]);
39862
41098
 
39863
41099
  // code under test
@@ -39934,7 +41170,7 @@ make root = ${bMakeRoot}`;
39934
41170
  }]
39935
41171
  }
39936
41172
  })
39937
- .expectChange("name", [""]) // triggered by setValue
41173
+ .expectChange("name", [""]) // invoked by setValue
39938
41174
  .expectMessages([{
39939
41175
  code : "1",
39940
41176
  message : "Enter a name",
@@ -40014,7 +41250,7 @@ make root = ${bMakeRoot}`;
40014
41250
  }]
40015
41251
  }
40016
41252
  })
40017
- .expectChange("name", [""]) // triggered by setValue
41253
+ .expectChange("name", [""]) // invoked by setValue
40018
41254
  .expectMessages([{
40019
41255
  code : "1",
40020
41256
  message : "Enter a name",
@@ -40621,7 +41857,7 @@ make root = ${bMakeRoot}`;
40621
41857
 
40622
41858
  //*********************************************************************************************
40623
41859
  // Scenario: Modifying a property of a kept-alive element in a list with
40624
- // $$patchWithoutSideEffects, triggers a side-effects refresh. The PATCH request does change the
41860
+ // $$patchWithoutSideEffects, invokes a side-effects refresh. The PATCH request does change the
40625
41861
  // ETag of the kept-alive element. The list refresh request does only add unknown properties
40626
41862
  // to the kept-alive element, but does not take over changed properties. The refresh for the
40627
41863
  // kept-alive element must do this.
@@ -42004,8 +43240,8 @@ make root = ${bMakeRoot}`;
42004
43240
  }]);
42005
43241
 
42006
43242
  return Promise.all([
42007
- oOperationBinding.execute(),
42008
- that.waitForChanges(assert, "execute")
43243
+ oOperationBinding.invoke(),
43244
+ that.waitForChanges(assert, "invoke")
42009
43245
  ]);
42010
43246
  }).then(function (aResults) {
42011
43247
  oReturnValueContext = aResults[0];
@@ -42179,7 +43415,7 @@ make root = ${bMakeRoot}`;
42179
43415
  });
42180
43416
 
42181
43417
  //*********************************************************************************************
42182
- // Scenario: A requestSideEffects and a bound action are triggered concurrently and end up in
43418
+ // Scenario: A requestSideEffects and a bound action are invoked concurrently and end up in
42183
43419
  // the same $batch. The requestSideEffects is already running when the action starts.
42184
43420
  // Nevertheless it must be possible to get the action's binding parameter from the cache being
42185
43421
  // updated.
@@ -42228,8 +43464,8 @@ make root = ${bMakeRoot}`;
42228
43464
  return Promise.all([
42229
43465
  that.oView.byId("form").getBindingContext().requestSideEffects(["SO_2_SOITEM"]),
42230
43466
  Promise.resolve().then(function () {
42231
- // code under test - execute while requestSideEffects is already being processed
42232
- return that.oView.byId("action").getObjectBinding().execute()
43467
+ // code under test - invoke while requestSideEffects is already being processed
43468
+ return that.oView.byId("action").getObjectBinding().invoke()
42233
43469
  .then(function (oReturnValueContext) {
42234
43470
  assert.strictEqual(oReturnValueContext, undefined,
42235
43471
  "no R.V.C. w/o key predicate");
@@ -42273,7 +43509,7 @@ make root = ${bMakeRoot}`;
42273
43509
  }, {/* don't care */});
42274
43510
 
42275
43511
  oRoomIdBinding.setValue("32");
42276
- }, function (assert) { // ODCB#execute restarts only PATCHes for the same entity
43512
+ }, function (assert) { // ODCB#invoke restarts only PATCHes for the same entity
42277
43513
  var sAction = "com.sap.gateway.default.iwbep.tea_busi.v0001.AcChangeTeamOfEmployee",
42278
43514
  oRoomIdBinding = this.oView.byId("roomId0").getBinding("value");
42279
43515
 
@@ -42292,10 +43528,10 @@ make root = ${bMakeRoot}`;
42292
43528
  payload : {TeamID : "23"}
42293
43529
  }, {/* don't care */});
42294
43530
 
42295
- // bound action also triggers retry
43531
+ // bound action also invokes retry
42296
43532
  return this.oModel.bindContext(sAction + "(...)", oRoomIdBinding.getContext())
42297
43533
  .setParameter("TeamID", "23")
42298
- .execute("$auto")
43534
+ .invoke("$auto")
42299
43535
  .then(function (oReturnValueContext) {
42300
43536
  assert.strictEqual(oReturnValueContext, undefined,
42301
43537
  "no R.V.C. w/o key predicate");
@@ -42364,7 +43600,7 @@ make root = ${bMakeRoot}`;
42364
43600
  this.oModel.bindContext("/ChangeTeamBudgetByID(...)")
42365
43601
  .setParameter("Budget", "1234.1234")
42366
43602
  .setParameter("TeamID", "TEAM_01")
42367
- .execute("$auto")
43603
+ .invoke("$auto")
42368
43604
  ]).then(function () {
42369
43605
  return /*bAll*/true;
42370
43606
  });
@@ -42649,9 +43885,9 @@ make root = ${bMakeRoot}`;
42649
43885
  });
42650
43886
 
42651
43887
  //*********************************************************************************************
42652
- // Scenario: ODCB#execute waits until PATCHes are back and happens inside same $batch as retry
43888
+ // Scenario: ODCB#invoke waits until PATCHes are back and happens inside same $batch as retry
42653
43889
  // (CPOUI5UISERVICESV3-1451)
42654
- QUnit.test("CPOUI5UISERVICESV3-1451: ODCB#execute after all PATCHes", function (assert) {
43890
+ QUnit.test("CPOUI5UISERVICESV3-1451: ODCB#invoke after all PATCHes", function (assert) {
42655
43891
  var oModel = this.createTeaBusiModel({groupId : "$direct", updateGroupId : "$auto"}),
42656
43892
  fnReject,
42657
43893
  oRoomIdBinding,
@@ -42730,10 +43966,10 @@ make root = ${bMakeRoot}`;
42730
43966
  payload : {TeamID : "23"}
42731
43967
  }, {/* don't care */});
42732
43968
 
42733
- // bound action waits for PATCHes and triggers retry
43969
+ // bound action waits for PATCHes and invokes retry
42734
43970
  oPromise = that.oModel.bindContext(sAction + "(...)", oRoomIdBinding.getContext())
42735
43971
  .setParameter("TeamID", "23")
42736
- .execute("$auto");
43972
+ .invoke("$auto");
42737
43973
 
42738
43974
  return Promise.all([
42739
43975
  oPromise.then(function (oReturnValueContext) {
@@ -42855,6 +44091,7 @@ make root = ${bMakeRoot}`;
42855
44091
  // Delete and Patch still use the canonical path. Messages have to be reported with the deep
42856
44092
  // path.
42857
44093
  // CPOUI5UISERVICESV3-1813
44094
+ // No "sap-cancel-on-close" header in DELETE request (JIRA: CPOUI5ODATAV4-2506)
42858
44095
  [false, true].forEach(function (bUseCanonicalPath) {
42859
44096
  QUnit.test("read with deep path, $$canonicalPath: " + bUseCanonicalPath, function (assert) {
42860
44097
  var sEntityPath = bUseCanonicalPath
@@ -42967,7 +44204,7 @@ make root = ${bMakeRoot}`;
42967
44204
  that.expectRequest({
42968
44205
  method : "DELETE",
42969
44206
  url : "ProductList('1')",
42970
- headers : {"If-Match" : "ETag"}
44207
+ headers : {"If-Match" : "ETag"/*, NO "sap-cancel-on-close" */}
42971
44208
  }, oError)
42972
44209
  .expectMessages([{
42973
44210
  code : "top_delete",
@@ -43742,11 +44979,11 @@ make root = ${bMakeRoot}`;
43742
44979
  });
43743
44980
  });
43744
44981
  //TODO With updateGroupId $direct, changing *both* parts of a composite binding (amount and
43745
- // currency) in one step triggers *two* PATCH requests:
44982
+ // currency) in one step invokes *two* PATCH requests:
43746
44983
  // The first request contains the new amount and also the old currency as PATCHes for amounts
43747
44984
  // are always sent with currency.
43748
44985
  // The second request only contains the new currency.
43749
- // Solution idea: Only execute $direct requests in prerendering task
44986
+ // Solution idea: Only invoke $direct requests in prerendering task
43750
44987
  // Is this critical? - Productive scenario runs with $batch. However: What if amount and
43751
44988
  // currency are in two different fields in draft scenario (no save button)?
43752
44989
 
@@ -43861,7 +45098,7 @@ make root = ${bMakeRoot}`;
43861
45098
  });
43862
45099
 
43863
45100
  //*********************************************************************************************
43864
- // Scenario: Execute a bound action on the target of a navigation property. That action returns
45101
+ // Scenario: Invoke a bound action on the target of a navigation property. That action returns
43865
45102
  // its binding parameter which is thus updated ("cache synchronization") and is the target of
43866
45103
  // messages.
43867
45104
  // CPOUI5UISERVICESV3-1587
@@ -43918,7 +45155,7 @@ make root = ${bMakeRoot}`;
43918
45155
 
43919
45156
  // code under test
43920
45157
  return Promise.all([
43921
- oOperation.execute(),
45158
+ oOperation.invoke(),
43922
45159
  that.waitForChanges(assert)
43923
45160
  ]);
43924
45161
  }).then(function () {
@@ -43960,7 +45197,7 @@ make root = ${bMakeRoot}`;
43960
45197
  IsActiveEntity : false
43961
45198
  });
43962
45199
 
43963
- return oOperationBinding.execute();
45200
+ return oOperationBinding.invoke();
43964
45201
  }).then(function (oReturnValueContext0) {
43965
45202
  oReturnValueContext = oReturnValueContext0;
43966
45203
 
@@ -43983,7 +45220,7 @@ make root = ${bMakeRoot}`;
43983
45220
  .expectChange("name", "Hour Frustrated");
43984
45221
 
43985
45222
  return Promise.all([
43986
- // Note: do not use oReturnValueContext, it would trigger duplicate requests
45223
+ // Note: do not use oReturnValueContext, it would invoke duplicate requests
43987
45224
  that.oView.byId("objectPage").getObjectBinding().getBoundContext()
43988
45225
  // code under test
43989
45226
  .requestSideEffects([{$PropertyPath : "Name"}]),
@@ -44125,7 +45362,7 @@ make root = ${bMakeRoot}`;
44125
45362
  });
44126
45363
 
44127
45364
  //*********************************************************************************************
44128
- // Scenario: GET request is triggered before POST, but ends up inside same $batch and thus
45365
+ // Scenario: GET request is invoked before POST, but ends up inside same $batch and thus
44129
45366
  // could return the newly created entity.
44130
45367
  // JIRA: CPOUI5UISERVICESV3-1825
44131
45368
  //
@@ -44177,7 +45414,7 @@ make root = ${bMakeRoot}`;
44177
45414
  "@odata.count" : "3",
44178
45415
  value : [{BusinessPartnerID : "4713"}]
44179
45416
  });
44180
- // show more items before POST is even triggered
45417
+ // show more items before POST is even invoked
44181
45418
  that.oView.byId("table").requestItems();
44182
45419
 
44183
45420
  that.expectChange("count", "4")
@@ -45078,7 +46315,7 @@ make root = ${bMakeRoot}`;
45078
46315
  }]);
45079
46316
 
45080
46317
  return Promise.all([
45081
- oOperationBinding.execute(),
46318
+ oOperationBinding.invoke(),
45082
46319
  that.waitForChanges(assert)
45083
46320
  ]);
45084
46321
  }).then(function (aResult) {
@@ -45106,7 +46343,7 @@ make root = ${bMakeRoot}`;
45106
46343
  });
45107
46344
 
45108
46345
  //*********************************************************************************************
45109
- // Scenario: Execute a bound action, this returns a return value context although the path
46346
+ // Scenario: Invoke a bound action, this returns a return value context although the path
45110
46347
  // contains navigation properties.
45111
46348
  // JIRA: CPOUI5ODATAV4-2096
45112
46349
  [false, true].forEach(function (bInheritExpandSelect) {
@@ -45191,7 +46428,7 @@ make root = ${bMakeRoot}`;
45191
46428
  const [oReturnValueContext] = await Promise.all([
45192
46429
  oActionBinding
45193
46430
  .setParameter("TeamID", sTeamId)
45194
- .execute(),
46431
+ .invoke(),
45195
46432
  this.waitForChanges(assert)
45196
46433
  ]);
45197
46434
 
@@ -45702,7 +46939,7 @@ make root = ${bMakeRoot}`;
45702
46939
 
45703
46940
  oForm.setBindingContext(
45704
46941
  that.oView.byId("table").getItems()[0].getBindingContext());
45705
- oForm.getElementBinding().execute();
46942
+ oForm.getElementBinding().invoke();
45706
46943
 
45707
46944
  return that.waitForChanges(assert);
45708
46945
  });
@@ -46237,7 +47474,7 @@ make root = ${bMakeRoot}`;
46237
47474
  type : "Error"
46238
47475
  }]);
46239
47476
 
46240
- // trigger error to see that hasPendingChanges finds also parked changes
47477
+ // invoke error to see that hasPendingChanges finds also parked changes
46241
47478
  that.oView.byId("soCurrencyCode").getBinding("value").setValue("invalid");
46242
47479
 
46243
47480
  assert.ok(oModel.hasPendingChanges());
@@ -46440,7 +47677,7 @@ make root = ${bMakeRoot}`;
46440
47677
  .expectChange("id", ["44", "43"])
46441
47678
  // Context#getIndex returns a negative number because the ODLB has been reset and thus
46442
47679
  // this.iCreatedContexts = 0;
46443
- // #create triggers Context#refreshDependentBindings before #rsE triggers
47680
+ // #create invokes Context#refreshDependentBindings before #rsE invokes
46444
47681
  // ODPaB#refreshDependentListBindingsWithoutCache, which seems natural (1st response is
46445
47682
  // processed 1st). Not sure how JIRA: CPOUI5ODATAV4-288 could help here.
46446
47683
  .expectChange("note", "Side", -1)
@@ -46705,7 +47942,7 @@ make root = ${bMakeRoot}`;
46705
47942
  that.waitForChanges(assert, "repeat POST but fail again")
46706
47943
  ]);
46707
47944
  }).then(function () {
46708
- oNewContext.setProperty("Note", "Updated", null); // do not trigger POST again
47945
+ oNewContext.setProperty("Note", "Updated", null); // do not invoke POST again
46709
47946
  assert.strictEqual(oNewContext.getProperty("Note"), "Updated");
46710
47947
 
46711
47948
  that.expectChange("id", ["", "0500000001"])
@@ -46814,7 +48051,7 @@ make root = ${bMakeRoot}`;
46814
48051
  })
46815
48052
  .expectChange("id", ["43"]);
46816
48053
 
46817
- // invocation here shall trigger all requests
48054
+ // invocation here shall invoke all requests
46818
48055
  fnRespond();
46819
48056
 
46820
48057
  return Promise.all([
@@ -46900,7 +48137,7 @@ make root = ${bMakeRoot}`;
46900
48137
  CompanyName : "SAP SE"
46901
48138
  });
46902
48139
 
46903
- // invocation here shall trigger all requests
48140
+ // invocation here shall invoke all requests
46904
48141
  fnRespond();
46905
48142
 
46906
48143
  return Promise.all([
@@ -46922,7 +48159,7 @@ make root = ${bMakeRoot}`;
46922
48159
  // For a context of a list binding, both a refresh of the whole collection and changes to
46923
48160
  // structural properties only ({"$PropertyPath":"*"}) are requested at the same time. Also, both
46924
48161
  // a refresh of the whole collection and of a single item ({$NavigationPropertyPath : ""}) are
46925
- // requested at the same time. No duplicate requests are triggered, no errors happen.
48162
+ // requested at the same time. No duplicate requests are invoked, no errors happen.
46926
48163
  // BCP: 2070206648
46927
48164
  QUnit.test("requestSideEffects: path reduction", function (assert) {
46928
48165
  var oContext,
@@ -47022,7 +48259,7 @@ make root = ${bMakeRoot}`;
47022
48259
  return Promise.all([
47023
48260
  // code under test
47024
48261
  oContext.requestSideEffects([
47025
- {$NavigationPropertyPath : ""}, // should not trigger a duplicate request
48262
+ {$NavigationPropertyPath : ""}, // should not invoke a duplicate request
47026
48263
  {$NavigationPropertyPath : "SOITEM_2_SO/SO_2_SOITEM"}
47027
48264
  ]),
47028
48265
  that.waitForChanges(assert)
@@ -47169,7 +48406,7 @@ make root = ${bMakeRoot}`;
47169
48406
  });
47170
48407
 
47171
48408
  //*********************************************************************************************
47172
- // Scenario: Refresh a context binding w/o property bindings triggering a request. Ensure that
48409
+ // Scenario: Refresh a context binding w/o property bindings invoking a request. Ensure that
47173
48410
  // dependent bindings refresh and that the promise resolves.
47174
48411
  // JIRA: CPOUI5ODATAV4-293
47175
48412
  QUnit.test("ODCB: requestRefresh w/o own request", function (assert) {
@@ -47742,7 +48979,7 @@ make root = ${bMakeRoot}`;
47742
48979
 
47743
48980
  //*********************************************************************************************
47744
48981
  // Scenario: Server-driven paging with sap.m.Table
47745
- // We expect a "growing" table to only load data when triggered by the end-user via the "More"
48982
+ // We expect a "growing" table to only load data when invoked by the end-user via the "More"
47746
48983
  // button: There are no repeated requests in case the server-side page size is 2 and thus
47747
48984
  // smaller than the table's growing threshold and just the first page is displayed with less
47748
48985
  // data. The next request is only sent when the end user wants to see "More".
@@ -48248,7 +49485,7 @@ make root = ${bMakeRoot}`;
48248
49485
  });
48249
49486
 
48250
49487
  //*********************************************************************************************
48251
- // Scenario: A PATCH (not shown here) triggers a side effect for the whole object page, while
49488
+ // Scenario: A PATCH (not shown here) invokes a side effect for the whole object page, while
48252
49489
  // a paginator switches to another item. The side effect's GET is thus ignored because the
48253
49490
  // cache for the old item is already inactive; thus the promise fails. Due to this failure, the
48254
49491
  // old cache was restored, which was wrong. Timing is essential!
@@ -48303,7 +49540,7 @@ make root = ${bMakeRoot}`;
48303
49540
  .expectChange("name", "Team #2");
48304
49541
 
48305
49542
  setTimeout(function () {
48306
- // pagination triggered by separate event --> new task
49543
+ // pagination invoked by separate event --> new task
48307
49544
  that.oView.setBindingContext(
48308
49545
  oModel.bindContext("/TEAMS('TEAM_02')").getBoundContext());
48309
49546
  setTimeout(fnRespond, 0);
@@ -48328,7 +49565,7 @@ make root = ${bMakeRoot}`;
48328
49565
  });
48329
49566
 
48330
49567
  //*********************************************************************************************
48331
- // Scenario: A PATCH (not shown here) triggers a side effect for the whole list, while a
49568
+ // Scenario: A PATCH (not shown here) invokes a side effect for the whole list, while a
48332
49569
  // paginator switches to another item. The side effect's GET is thus ignored because the cache
48333
49570
  // for the old item is already inactive; thus an internal promise fails. Due to this failure,
48334
49571
  // the old cache was restored, which was wrong. Timing is essential!
@@ -48392,7 +49629,7 @@ make root = ${bMakeRoot}`;
48392
49629
  .expectChange("name", ["Frederic Fall"]);
48393
49630
 
48394
49631
  setTimeout(function () {
48395
- // pagination triggered by separate event --> new task
49632
+ // pagination invoked by separate event --> new task
48396
49633
  oTable.setBindingContext(oModel.bindContext("/TEAMS('TEAM_02')").getBoundContext());
48397
49634
  setTimeout(fnRespond, 0);
48398
49635
  }, 0);
@@ -49000,7 +50237,7 @@ make root = ${bMakeRoot}`;
49000
50237
  });
49001
50238
 
49002
50239
  //*********************************************************************************************
49003
- // Scenario: A bound action is executed, accompanied by a side effect. The action returns a
50240
+ // Scenario: A bound action is invoked, accompanied by a side effect. The action returns a
49004
50241
  // wrong response, but the side effect must win anyway!
49005
50242
  // BCP: 2070200175
49006
50243
  // JIRA: CPOUI5ODATAV4-288
@@ -49038,7 +50275,7 @@ make root = ${bMakeRoot}`;
49038
50275
  .expectChange("status", "C");
49039
50276
 
49040
50277
  return Promise.all([
49041
- that.oView.byId("action").getObjectBinding().execute(),
50278
+ that.oView.byId("action").getObjectBinding().invoke(),
49042
50279
  that.oView.byId("form").getBindingContext().requestSideEffects(["LifecycleStatus"]),
49043
50280
  that.waitForChanges(assert)
49044
50281
  ]);
@@ -49047,13 +50284,13 @@ make root = ${bMakeRoot}`;
49047
50284
 
49048
50285
  //*********************************************************************************************
49049
50286
  // Scenario: "Prefer:handling=strict"
49050
- // Execute an action with an fnOnStrictHandlingFailed callback given in order to have the
50287
+ // Invoke an action with an fnOnStrictHandlingFailed callback given in order to have the
49051
50288
  // "Prefer:handling=strict" HTTP header set. bConfirm controls how the callback is resolved.
49052
50289
  //
49053
50290
  // JIRA: CPOUI5ODATAV4-943
49054
50291
  // BCP: 2280172148 more than one action in change set + check that the right callback is called
49055
50292
  //
49056
- // Execute three actions in a changeset, each with a fnOnStrictHandlingFailed handler. The batch
50293
+ // Invoke three actions in a changeset, each with a fnOnStrictHandlingFailed handler. The batch
49057
50294
  // fails due to strict-handling and the response contains error messages for the first and
49058
50295
  // second request or only for the first. No error message for the third request. See that each
49059
50296
  // handler is called with the correct (or none) errors.
@@ -49207,11 +50444,11 @@ make root = ${bMakeRoot}`;
49207
50444
 
49208
50445
  // code under test
49209
50446
  oAction0Promise = that.oModel.bindContext(sAction + "(...)", aContexts[0])
49210
- .execute("$auto", false, onStrictHandlingFailed0);
50447
+ .invoke("$auto", false, onStrictHandlingFailed0);
49211
50448
  oAction1Promise = that.oModel.bindContext(sAction + "(...)", aContexts[1])
49212
- .execute("$auto", false, onStrictHandlingFailed1);
50449
+ .invoke("$auto", false, onStrictHandlingFailed1);
49213
50450
  oAction2Promise = that.oModel.bindContext(sAction + "(...)", aContexts[2])
49214
- .execute("$auto", false, onStrictHandlingFailed2);
50451
+ .invoke("$auto", false, onStrictHandlingFailed2);
49215
50452
 
49216
50453
  return that.waitForChanges(assert);
49217
50454
  }).then(function () {
@@ -49248,11 +50485,11 @@ make root = ${bMakeRoot}`;
49248
50485
  })
49249
50486
  .expectChange("status", ["C0", "C1", "C2"]);
49250
50487
  } else {
49251
- that.expectCanceledError("Failed to execute /SalesOrderList('0')/" + sAction
50488
+ that.expectCanceledError("Failed to invoke /SalesOrderList('0')/" + sAction
49252
50489
  + "(...)", "Action canceled due to strict handling");
49253
- that.expectCanceledError("Failed to execute /SalesOrderList('1')/" + sAction
50490
+ that.expectCanceledError("Failed to invoke /SalesOrderList('1')/" + sAction
49254
50491
  + "(...)", "Action canceled due to strict handling");
49255
- that.expectCanceledError("Failed to execute /SalesOrderList('2')/" + sAction
50492
+ that.expectCanceledError("Failed to invoke /SalesOrderList('2')/" + sAction
49256
50493
  + "(...)", "Action canceled due to strict handling");
49257
50494
  }
49258
50495
 
@@ -49292,14 +50529,14 @@ make root = ${bMakeRoot}`;
49292
50529
 
49293
50530
  //*********************************************************************************************
49294
50531
  // Scenario: "Prefer:handling=strict"
49295
- // 1. Successful execution of a) a bound and b) an unbound action with "handling=strict" in the
50532
+ // 1. Successful invocation of a) a bound and b) an unbound action with "handling=strict" in the
49296
50533
  // same change set
49297
- // 2. Another execution of a bound action with "handling=strict" in a different change set (of
50534
+ // 2. Another invocation of a bound action with "handling=strict" in a different change set (of
49298
50535
  // the same $batch) that will result in a rejection of this action
49299
50536
  // 3. Test whether "handling=strict" is allowed only for an action
49300
50537
  //
49301
50538
  // JIRA: CPOUI5ODATAV4-943
49302
- QUnit.test("CPOUI5ODATAV4-943: handling=strict, multiple strict executions", function (assert) {
50539
+ QUnit.test("CPOUI5ODATAV4-943: handling=strict, many strict invocations", function (assert) {
49303
50540
  var sAction = "com.sap.gateway.default.zui5_epm_sample.v0002.SalesOrder_Confirm",
49304
50541
  oContext,
49305
50542
  oModel = this.createSalesOrdersModel({autoExpandSelect : true}),
@@ -49319,13 +50556,13 @@ make root = ${bMakeRoot}`;
49319
50556
  oContext = that.oView.byId("form").getBindingContext();
49320
50557
 
49321
50558
  that.oLogMock.expects("error")
49322
- .withExactArgs("Failed to execute /SalesOrderList('0')/"
50559
+ .withExactArgs("Failed to invoke /SalesOrderList('0')/"
49323
50560
  + "com.sap.gateway.default.zui5_epm_sample.v0002.SalesOrder_Confirm(...)",
49324
50561
  sinon.match(
49325
50562
  "All requests with strict handling must belong to the same change set"),
49326
50563
  sODCB);
49327
50564
  that.oLogMock.expects("error")
49328
- .withExactArgs("Failed to execute /GetProductStock(...)",
50565
+ .withExactArgs("Failed to invoke /GetProductStock(...)",
49329
50566
  sinon.match("Not an action: /GetProductStock(...)"), sODCB);
49330
50567
  that.expectRequest({
49331
50568
  headers : {
@@ -49364,24 +50601,24 @@ make root = ${bMakeRoot}`;
49364
50601
  return Promise.all([
49365
50602
  // only to issue a GET request (non change set) at the beginning
49366
50603
  oModel.bindContext("/GetProductStock(...)")
49367
- .execute("confirm"),
50604
+ .invoke("confirm"),
49368
50605
  // code under test (1a)
49369
50606
  oModel.bindContext(sAction + "(...)", oContext)
49370
- .execute("confirm", false, function () {}),
50607
+ .invoke("confirm", false, function () {}),
49371
50608
  // code under test (1b)
49372
50609
  oModel.bindContext("/RegenerateEPMData(...)")
49373
- .execute("confirm", false, function () {}),
50610
+ .invoke("confirm", false, function () {}),
49374
50611
  oModel.submitBatch("confirm"), //create 2nd change set in $batch
49375
50612
  // code under test (2)
49376
50613
  oModel.bindContext(sAction + "(...)", oContext)
49377
- .execute("confirm", false, function () {})
50614
+ .invoke("confirm", false, function () {})
49378
50615
  .then(mustFail(assert), function (oError) {
49379
50616
  assert.strictEqual(oError.message,
49380
50617
  "All requests with strict handling must belong to the same change set");
49381
50618
  }),
49382
50619
  // code under test (3)
49383
50620
  oModel.bindContext("/GetProductStock(...)")
49384
- .execute("confirm", false, function () {})
50621
+ .invoke("confirm", false, function () {})
49385
50622
  .then(mustFail(assert), function (oError) {
49386
50623
  assert.strictEqual(oError.message,
49387
50624
  "Not an action: /GetProductStock(...)");
@@ -49466,7 +50703,7 @@ make root = ${bMakeRoot}`;
49466
50703
  }, oError, {
49467
50704
  "Preference-Applied" : "handling=strict"
49468
50705
  })
49469
- .expectCanceledError("Failed to execute /SalesOrderList('42')/" + sGoodsAction
50706
+ .expectCanceledError("Failed to invoke /SalesOrderList('42')/" + sGoodsAction
49470
50707
  + "(...)", "Action canceled due to strict handling")
49471
50708
  .expectMessages([{
49472
50709
  code : "CODE",
@@ -49479,10 +50716,10 @@ make root = ${bMakeRoot}`;
49479
50716
 
49480
50717
  // code under test
49481
50718
  return Promise.all([
49482
- oConfirmBinding.execute("confirm"),
50719
+ oConfirmBinding.invoke("confirm"),
49483
50720
  oModel.submitBatch("confirm"),
49484
50721
  checkCanceled(assert,
49485
- oGoodsBinding.execute("confirm", false, fnStrictHandlingFailed)),
50722
+ oGoodsBinding.invoke("confirm", false, fnStrictHandlingFailed)),
49486
50723
  oModel.submitBatch("confirm"),
49487
50724
  that.waitForChanges(assert)
49488
50725
  ]);
@@ -50336,9 +51573,9 @@ make root = ${bMakeRoot}`;
50336
51573
  });
50337
51574
 
50338
51575
  //*********************************************************************************************
50339
- // Scenario: Executing an action is forbidden for models with shared requests.
51576
+ // Scenario: Invoking an action is forbidden for models with shared requests.
50340
51577
  // JIRA: CPOUI5ODATAV4-344
50341
- QUnit.test("sharedRequests forbids action execute", function (assert) {
51578
+ QUnit.test("sharedRequests forbids action invoke", function (assert) {
50342
51579
  var oModel = this.createTeaBusiModel({sharedRequests : true}),
50343
51580
  that = this;
50344
51581
 
@@ -50347,10 +51584,10 @@ make root = ${bMakeRoot}`;
50347
51584
  sMessage = sTeaBusi + "ChangeTeamBudgetByID is read-only";
50348
51585
 
50349
51586
  that.oLogMock.expects("error")
50350
- .withExactArgs("Failed to execute /ChangeTeamBudgetByID(...)",
51587
+ .withExactArgs("Failed to invoke /ChangeTeamBudgetByID(...)",
50351
51588
  sinon.match(sMessage), sODCB);
50352
51589
 
50353
- return oAction.execute().then(mustFail(assert), function (oError) {
51590
+ return oAction.invoke().then(mustFail(assert), function (oError) {
50354
51591
  assert.strictEqual(oError.message, sMessage);
50355
51592
  });
50356
51593
  });
@@ -50432,7 +51669,7 @@ make root = ${bMakeRoot}`;
50432
51669
  this.expectChange("name", []);
50433
51670
 
50434
51671
  return this.createView(assert, sView, oModel).then(function () {
50435
- // Note: GET triggered by 1st #create - one transient taken into account for prefetch
51672
+ // Note: GET invoked by 1st #create - one transient taken into account for prefetch
50436
51673
  that.expectRequest("EMPLOYEES?$count=true&$select=ID,Name&$skip=0&$top=3", {
50437
51674
  "@odata.count" : "1",
50438
51675
  value : [{ID : "1", Name : "Frederic Fall"}]
@@ -50685,7 +51922,7 @@ make root = ${bMakeRoot}`;
50685
51922
  // code under test
50686
51923
  oModel.submitBatch(sGroupId),
50687
51924
  // code under test (JIRA: CPOUI5ODATAV4-2134)
50688
- oModel.bindContext("/RegenerateEPMData(...)").execute(sGroupId),
51925
+ oModel.bindContext("/RegenerateEPMData(...)").invoke(sGroupId),
50689
51926
  oContext1.created(),
50690
51927
  that.waitForChanges(assert, "(3)")
50691
51928
  ]);
@@ -50940,7 +52177,7 @@ make root = ${bMakeRoot}`;
50940
52177
  //*********************************************************************************************
50941
52178
  // Scenario: Apply the filter for messages on a table with persisted and inactive rows, but only
50942
52179
  // messages for inactive rows. See that the persisted rows disappear w/o a request, and see that
50943
- // selected APIs do not trigger requests afterwards.
52180
+ // selected APIs do not invoke requests afterwards.
50944
52181
  // Run each test with a grid table, a responsive table, and a responsive table with growing
50945
52182
  // enablement. Check that #setAggregation does not work with Filter.NONE, download URL is null,
50946
52183
  // and #requestContexts (with Filter.NONE) returns transient rows only without a GET request.
@@ -53821,7 +55058,7 @@ make root = ${bMakeRoot}`;
53821
55058
  }]);
53822
55059
 
53823
55060
  return Promise.all([
53824
- oActionBinding.execute(undefined, undefined, undefined, /*bReplaceWithRVC*/true),
55061
+ oActionBinding.invoke(undefined, undefined, undefined, /*bReplaceWithRVC*/true),
53825
55062
  that.waitForChanges(assert, "(3) edit action")
53826
55063
  ]);
53827
55064
  }).then(function (aResults) {
@@ -55450,11 +56687,11 @@ make root = ${bMakeRoot}`;
55450
56687
  //*********************************************************************************************
55451
56688
  // Scenario: New change requests for the same group ID (e.g. $auto) are submitted before the
55452
56689
  // previous response arrives, leading to the error "Unexpected second $batch". Here,
55453
- // ODataContextBinding#execute is used.
56690
+ // ODataContextBinding#invoke is used.
55454
56691
  // BCP: 2170018878
55455
- QUnit.test("BCP: 2170018878 via ODCB#execute", function (assert) {
55456
- var oExecutePromise0,
55457
- oExecutePromise1,
56692
+ QUnit.test("BCP: 2170018878 via ODCB#invoke", function (assert) {
56693
+ var oInvokePromise0,
56694
+ oInvokePromise1,
55458
56695
  fnResolveOperation0,
55459
56696
  fnResolveOperation1,
55460
56697
  that = this;
@@ -55473,7 +56710,7 @@ make root = ${bMakeRoot}`;
55473
56710
  }));
55474
56711
 
55475
56712
  // code under test
55476
- oExecutePromise0 = oOperationBinding.execute();
56713
+ oInvokePromise0 = oOperationBinding.invoke();
55477
56714
 
55478
56715
  return that.waitForChanges(assert);
55479
56716
  }).then(function () {
@@ -55490,17 +56727,17 @@ make root = ${bMakeRoot}`;
55490
56727
  }));
55491
56728
 
55492
56729
  // code under test
55493
- oExecutePromise1 = oOperationBinding.execute();
56730
+ oInvokePromise1 = oOperationBinding.invoke();
55494
56731
 
55495
56732
  return that.waitForChanges(assert);
55496
56733
  }).then(function () {
55497
56734
  fnResolveOperation1();
55498
56735
 
55499
- return oExecutePromise1;
56736
+ return oInvokePromise1;
55500
56737
  }).then(function () {
55501
56738
  fnResolveOperation0();
55502
56739
 
55503
- return oExecutePromise0;
56740
+ return oInvokePromise0;
55504
56741
  });
55505
56742
  });
55506
56743
 
@@ -56109,8 +57346,8 @@ make root = ${bMakeRoot}`;
56109
57346
 
56110
57347
  return Promise.all([
56111
57348
  // code under test
56112
- oAction.execute(),
56113
- that.waitForChanges(assert, "(1) execute")
57349
+ oAction.invoke(),
57350
+ that.waitForChanges(assert, "(1) invoke")
56114
57351
  ]);
56115
57352
  }).then(function (aResults) {
56116
57353
  that.expectChange("note", "some note");
@@ -57206,7 +58443,7 @@ make root = ${bMakeRoot}`;
57206
58443
  that.waitForChanges(assert, "removeCreated")
57207
58444
  ]);
57208
58445
  }).then(function () {
57209
- // Note: this triggers ODLB#destroyPreviousContextsLater, thus we need to wait below
58446
+ // Note: this invokes ODLB#destroyPreviousContextsLater, thus we need to wait below
57210
58447
  var aAllContexts = oBinding.getAllCurrentContexts();
57211
58448
 
57212
58449
  assert.strictEqual(aAllContexts.length, 1);
@@ -60163,7 +61400,7 @@ make root = ${bMakeRoot}`;
60163
61400
  // Scenario:
60164
61401
  // (1) Binding for a part of a structural instance annotation works without binding the
60165
61402
  // property itself
60166
- // (2) Late request for another annotation of the same property does not trigger a GET request
61403
+ // (2) Late request for another annotation of the same property does not invoke a GET request
60167
61404
  // (3) Late request for an instance annotation which was not requested before
60168
61405
  // (4), (5) Edm.Stream simulation: initial response is empty, no further requests
60169
61406
  // (6) Request side effects for property of (4), empty response
@@ -60926,7 +62163,7 @@ make root = ${bMakeRoot}`;
60926
62163
  });
60927
62164
 
60928
62165
  //*********************************************************************************************
60929
- // Scenario: Create a new draft entity and execute the ActivationAction to replace the draft
62166
+ // Scenario: Create a new draft entity and invoke the ActivationAction to replace the draft
60930
62167
  // context with the active context. Request a side-effects refresh for the active context.
60931
62168
  // BCP: 2180347338
60932
62169
  // BCP: 2280113990
@@ -60996,9 +62233,9 @@ make root = ${bMakeRoot}`;
60996
62233
 
60997
62234
  return Promise.all([
60998
62235
  // code under test
60999
- oActionBinding.execute(/*sGroupId*/undefined, /*bIgnoreETag*/false,
62236
+ oActionBinding.invoke(/*sGroupId*/undefined, /*bIgnoreETag*/false,
61000
62237
  /*fnOnStrictHandlingFailed*/null, /*bReplaceWithRVC*/true),
61001
- that.waitForChanges(assert, "execute ActivationAction")
62238
+ that.waitForChanges(assert, "invoke ActivationAction")
61002
62239
  ]);
61003
62240
  }).then(function (aResults) {
61004
62241
  oActiveContext = aResults[0];
@@ -61038,7 +62275,7 @@ make root = ${bMakeRoot}`;
61038
62275
  });
61039
62276
 
61040
62277
  //*********************************************************************************************
61041
- // Scenario: In an ODLB w/ filter, but w/o UI, create a new draft entity and execute the
62278
+ // Scenario: In an ODLB w/ filter, but w/o UI, create a new draft entity and invoke the
61042
62279
  // ActivationAction to replace the draft context with the active context. Refresh the active
61043
62280
  // context in order to make it drop out of the collection, alternatively delete it. See that
61044
62281
  // internal bookkeeping is OK by creating an inactive row at the other end.
@@ -61100,8 +62337,8 @@ make root = ${bMakeRoot}`;
61100
62337
 
61101
62338
  return Promise.all([
61102
62339
  // code under test
61103
- oActionBinding.execute(undefined, false, null, /*bReplaceWithRVC*/true),
61104
- that.waitForChanges(assert, "execute ActivationAction")
62340
+ oActionBinding.invoke(undefined, false, null, /*bReplaceWithRVC*/true),
62341
+ that.waitForChanges(assert, "invoke ActivationAction")
61105
62342
  ]);
61106
62343
  }).then(function (aResults) {
61107
62344
  oActiveContext = aResults[0];
@@ -61142,12 +62379,12 @@ make root = ${bMakeRoot}`;
61142
62379
  });
61143
62380
 
61144
62381
  //*********************************************************************************************
61145
- // Scenario: In an ODLB w/ filter, but w/o UI, create a new draft entity and execute the
62382
+ // Scenario: In an ODLB w/ filter, but w/o UI, create a new draft entity and invoke the
61146
62383
  // ActivationAction to replace the draft context with the active context. Keep the active
61147
62384
  // context alive and refresh it in order to make it drop out of the collection. See that it is
61148
62385
  // still alive.
61149
62386
  //
61150
- // Execute the EditAction with empty response to check that bReplaceWithRVC requires a key
62387
+ // Invoke the EditAction with empty response to check that bReplaceWithRVC requires a key
61151
62388
  // predicate.
61152
62389
  // JIRA: CPOUI5ODATAV4-1683
61153
62390
  QUnit.test("JIRA: CPOUI5ODATAV4-1683", function (assert) {
@@ -61193,8 +62430,8 @@ make root = ${bMakeRoot}`;
61193
62430
 
61194
62431
  return Promise.all([
61195
62432
  // code under test
61196
- oActionBinding.execute(undefined, false, null, /*bReplaceWithRVC*/true),
61197
- that.waitForChanges(assert, "execute ActivationAction")
62433
+ oActionBinding.invoke(undefined, false, null, /*bReplaceWithRVC*/true),
62434
+ that.waitForChanges(assert, "invoke ActivationAction")
61198
62435
  ]);
61199
62436
  }).then(function (aResults) {
61200
62437
  oActiveContext = aResults[0];
@@ -61236,18 +62473,18 @@ make root = ${bMakeRoot}`;
61236
62473
  type : "Error"
61237
62474
  }]);
61238
62475
  that.oLogMock.expects("error")
61239
- .withExactArgs("Failed to execute /Artists(ArtistID='23',IsActiveEntity=true)"
62476
+ .withExactArgs("Failed to invoke /Artists(ArtistID='23',IsActiveEntity=true)"
61240
62477
  + "/special.cases.EditAction(...)",
61241
62478
  sinon.match("Cannot replace w/o return value context"), sODCB);
61242
62479
 
61243
62480
  return Promise.all([
61244
62481
  // code under test
61245
- oActionBinding.execute(undefined, false, null, /*bReplaceWithRVC*/true)
62482
+ oActionBinding.invoke(undefined, false, null, /*bReplaceWithRVC*/true)
61246
62483
  .then(mustFail(assert), function (oError) {
61247
62484
  assert.strictEqual(oError.message,
61248
62485
  "Cannot replace w/o return value context");
61249
62486
  }),
61250
- that.waitForChanges(assert, "execute EditAction")
62487
+ that.waitForChanges(assert, "invoke EditAction")
61251
62488
  ]);
61252
62489
  });
61253
62490
  });
@@ -61315,7 +62552,7 @@ make root = ${bMakeRoot}`;
61315
62552
 
61316
62553
  //*********************************************************************************************
61317
62554
  // Scenario: A return value context is destroyed as soon as a new cache is created during
61318
- // #execute, no matter what happens after that.
62555
+ // #invoke, no matter what happens after that.
61319
62556
  //
61320
62557
  // JIRA: CPOUI5ODATAV4-1687
61321
62558
  QUnit.test("JIRA: CPOUI5ODATAV4-1687", function (assert) {
@@ -61356,7 +62593,7 @@ make root = ${bMakeRoot}`;
61356
62593
  .expectChange("team", "TEAM_02");
61357
62594
 
61358
62595
  return Promise.all([
61359
- oActionBinding.execute(),
62596
+ oActionBinding.invoke(),
61360
62597
  that.waitForChanges(assert)
61361
62598
  ]);
61362
62599
  }).then(function (aResults) {
@@ -61377,7 +62614,7 @@ make root = ${bMakeRoot}`;
61377
62614
 
61378
62615
  return Promise.all([
61379
62616
  // code under test
61380
- oActionBinding.setParameter("TeamID", "TEAM_0815").execute(),
62617
+ oActionBinding.setParameter("TeamID", "TEAM_0815").invoke(),
61381
62618
  that.waitForChanges(assert)
61382
62619
  ]);
61383
62620
  }).then(function (aResults) {
@@ -61427,7 +62664,7 @@ make root = ${bMakeRoot}`;
61427
62664
  });
61428
62665
 
61429
62666
  return Promise.all([
61430
- oAction.execute(),
62667
+ oAction.invoke(),
61431
62668
  that.waitForChanges(assert, "edit")
61432
62669
  ]);
61433
62670
  }).then(function (aResults) {
@@ -62246,7 +63483,7 @@ make root = ${bMakeRoot}`;
62246
63483
 
62247
63484
  return Promise.all([
62248
63485
  // code under test
62249
- oSiblingEntity.execute("$auto", /*bIgnoreETag*/false,
63486
+ oSiblingEntity.invoke("$auto", /*bIgnoreETag*/false,
62250
63487
  /*fnOnStrictHandlingFailed*/null, /*bReplaceWithRVC*/true),
62251
63488
  that.waitForChanges(assert, "SiblingEntity")
62252
63489
  ]);
@@ -62343,6 +63580,7 @@ make root = ${bMakeRoot}`;
62343
63580
  // ODM#submitBatch. Expect that the latter's promise does not resolve before the create request
62344
63581
  // is completed.
62345
63582
  // BCP: 2370151708
63583
+ // No "sap-cancel-on-close" header in POST request (JIRA: CPOUI5ODATAV4-2506)
62346
63584
  QUnit.test("BCP: 2370151708 - submitBatch includes create ($auto)", async function (assert) {
62347
63585
  const oModel = this.createTeaBusiModel({autoExpandSelect : true});
62348
63586
  await this.createView(assert, "", oModel);
@@ -62350,6 +63588,7 @@ make root = ${bMakeRoot}`;
62350
63588
  let fnResolveCreate;
62351
63589
  this.expectRequest({
62352
63590
  method : "POST",
63591
+ headers : {/*NO "sap-cancel-on-close"*/},
62353
63592
  payload : {},
62354
63593
  url : "EMPLOYEES"
62355
63594
  }, new Promise(function (resolve) {
@@ -62377,11 +63616,11 @@ make root = ${bMakeRoot}`;
62377
63616
  });
62378
63617
 
62379
63618
  //*********************************************************************************************
62380
- // Scenario: Execute actions and delete rows using group id "$single" and "$direct". Observe
62381
- // that each execute and delete request using "$single" is in its own batch request and does not
63619
+ // Scenario: Invoke actions and delete rows using group id "$single" and "$direct". Observe
63620
+ // that each invoke and delete request using "$single" is in its own batch request and does not
62382
63621
  // get overtaken by the "$direct" request.
62383
63622
  // JIRA: CPOUI5ODATAV4-2413
62384
- QUnit.test("Execute and delete immediately using groupId='$single'", async function (assert) {
63623
+ QUnit.test("Invoke and delete immediately using groupId='$single'", async function (assert) {
62385
63624
  const oModel = this.createSalesOrdersModel({autoExpandSelect : true});
62386
63625
  const sView = `
62387
63626
  <Table id="orders" items="{/SalesOrderList}">
@@ -62433,9 +63672,9 @@ make root = ${bMakeRoot}`;
62433
63672
  const oContextBinding1 = oModel.bindContext(sAction + "(...)", oContext1);
62434
63673
  const oContextBinding2 = oModel.bindContext(sAction + "(...)", oContext2);
62435
63674
 
62436
- const oRVCPromise0 = oContextBinding0.execute("$single");
62437
- const oRVCPromise1 = oContextBinding1.execute("$single");
62438
- const oRVCPromise2 = oContextBinding2.execute("$direct");
63675
+ const oRVCPromise0 = oContextBinding0.invoke("$single");
63676
+ const oRVCPromise1 = oContextBinding1.invoke("$single");
63677
+ const oRVCPromise2 = oContextBinding2.invoke("$direct");
62439
63678
 
62440
63679
  await Promise.all([
62441
63680
  // code under test
@@ -62508,31 +63747,35 @@ make root = ${bMakeRoot}`;
62508
63747
  // JIRA: CPOUI5ODATAV4-1944
62509
63748
  //
62510
63749
  // Select a header context via all three possible ways: setSelected and write to the annotation
62511
- // via context or property binding. Swap the context of the "selectAll" property binding and
62512
- // check if change listeners are correctly removed.
63750
+ // via context or property binding. Selecting the header context selects and deselects all row
63751
+ // contexts. A newly created inactive (and transient) row is also selected. Newly loaded rows
63752
+ // inherit the selection from the header context. Swap the context of the "select all" property
63753
+ // binding and check if change listeners are correctly removed.
62513
63754
  // JIRA: CPOUI5ODATAV4-2493
62514
63755
  QUnit.test("Selection on header context and row context", async function (assert) {
62515
63756
  const oModel = this.createSalesOrdersModel({autoExpandSelect : true});
62516
63757
  const sView = `
62517
63758
  <Input id="selectAll" value="{path: '@$ui5.context.isSelected', targetType: 'any'}"/>
62518
- <Table id="table" items="{/SalesOrderList}">
63759
+ <Table id="table" growing="true" growingThreshold="3" items="{/SalesOrderList}">
62519
63760
  <Text id="id" text="{SalesOrderID}"/>
62520
63761
  <Input id="selected" value="{path : '@$ui5.context.isSelected', targetType: 'any'}"/>
62521
63762
  </Table>`;
62522
63763
 
62523
- this.expectRequest("SalesOrderList?$select=SalesOrderID&$skip=0&$top=100", {
63764
+ this.expectRequest("SalesOrderList?$select=SalesOrderID&$skip=0&$top=3", {
62524
63765
  value : [
62525
- {SalesOrderID : "1"}
62526
- ]
63766
+ {SalesOrderID : "1"},
63767
+ {SalesOrderID : "2"},
63768
+ {SalesOrderID : "3"}
63769
+ ]
62527
63770
  })
62528
63771
  .expectChange("selectAll")
62529
- .expectChange("id", ["1"])
62530
- .expectChange("selected", [undefined]);
63772
+ .expectChange("id", ["1", "2", "3"])
63773
+ .expectChange("selected", [undefined, undefined, undefined]);
62531
63774
 
62532
63775
  await this.createView(assert, sView, oModel);
62533
63776
 
62534
- const oPropertyBinding = this.oView.byId("table").getItems()[0].getCells()[1]
62535
- .getBinding("value");
63777
+ const oTable = this.oView.byId("table");
63778
+ const oPropertyBinding = oTable.getItems()[0].getCells()[1].getBinding("value");
62536
63779
  const oContext = oPropertyBinding.getContext();
62537
63780
 
62538
63781
  this.expectChange("selected", [true]);
@@ -62541,7 +63784,7 @@ make root = ${bMakeRoot}`;
62541
63784
  oPropertyBinding.setValue(true);
62542
63785
 
62543
63786
  checkSelected(assert, oContext, true);
62544
- await this.waitForChanges(assert);
63787
+ await this.waitForChanges(assert, "rowContext selected");
62545
63788
 
62546
63789
  this.expectChange("selected", [false]);
62547
63790
 
@@ -62549,67 +63792,104 @@ make root = ${bMakeRoot}`;
62549
63792
  oPropertyBinding.setValue(false);
62550
63793
 
62551
63794
  checkSelected(assert, oContext, false);
62552
- await this.waitForChanges(assert);
63795
+ await this.waitForChanges(assert, "rowContext deselected");
62553
63796
 
62554
- const oHeaderContext = this.oView.byId("table").getBinding("items").getHeaderContext();
63797
+ const oListBinding = oTable.getBinding("items");
63798
+ const oHeaderContext = oListBinding.getHeaderContext();
62555
63799
  const oSelectAllInput = this.oView.byId("selectAll");
62556
63800
  oSelectAllInput.setBindingContext(oHeaderContext);
62557
63801
  const oSelectAllBinding = oSelectAllInput.getBinding("value");
62558
63802
 
62559
- this.expectChange("selectAll", true);
63803
+ this.expectChange("selectAll", true)
63804
+ .expectChange("selected", [true, true, true]);
62560
63805
 
62561
63806
  // code under test
62562
63807
  oSelectAllBinding.setValue(true);
62563
63808
 
62564
63809
  checkSelected(assert, oHeaderContext, true);
62565
- await this.waitForChanges(assert);
63810
+ await this.waitForChanges(assert, "headerContext selected via setValue");
63811
+
63812
+ this.expectChange("id", [""])
63813
+ .expectChange("selected", [true]);
63814
+
63815
+ // code under test - newly created row context is selected
63816
+ const oInactiveContext = oListBinding.create(undefined, true, false, true);
63817
+
63818
+ assert.ok(oInactiveContext.isTransient());
63819
+ assert.ok(oInactiveContext.isInactive());
63820
+ assert.ok(oInactiveContext.isSelected());
63821
+
63822
+ await this.waitForChanges(assert, "new row is selected");
62566
63823
 
62567
- this.expectChange("selectAll", false);
63824
+ this.expectChange("selectAll", false)
63825
+ .expectChange("selected", [false, false, false]);
62568
63826
 
62569
63827
  // code under test
62570
63828
  oSelectAllBinding.setValue(false);
62571
63829
 
62572
63830
  checkSelected(assert, oHeaderContext, false);
62573
- await this.waitForChanges(assert);
63831
+ await this.waitForChanges(assert, "headerContext deselected via setValue");
62574
63832
 
62575
- this.expectChange("selectAll", true);
63833
+ this.expectChange("selectAll", true)
63834
+ .expectChange("selected", [true, true, true]);
62576
63835
 
62577
63836
  // code under test
62578
63837
  oHeaderContext.setProperty("@$ui5.context.isSelected", true);
62579
63838
 
62580
63839
  checkSelected(assert, oHeaderContext, true);
62581
- await this.waitForChanges(assert);
63840
+ await this.waitForChanges(assert, "headerContext selected via setProperty");
62582
63841
 
62583
- this.expectChange("selectAll", false);
63842
+ this.expectChange("selectAll", false)
63843
+ .expectChange("selected", [false, false, false]);
62584
63844
 
62585
63845
  // code under test
62586
63846
  oHeaderContext.setProperty("@$ui5.context.isSelected", false);
62587
63847
 
62588
63848
  checkSelected(assert, oHeaderContext, false);
62589
- await this.waitForChanges(assert);
63849
+ await this.waitForChanges(assert, "headerContext deselected via setProperty");
62590
63850
 
62591
- this.expectChange("selectAll", true);
63851
+ this.expectChange("selectAll", true)
63852
+ .expectChange("selected", [true, true, true]);
62592
63853
 
62593
63854
  // code under test
62594
63855
  oHeaderContext.setSelected(true);
62595
63856
 
62596
63857
  checkSelected(assert, oHeaderContext, true);
62597
- await this.waitForChanges(assert);
63858
+ await this.waitForChanges(assert, "headerContext selected via setSelected");
62598
63859
 
62599
- this.expectChange("selectAll", false);
63860
+ this.expectRequest("SalesOrderList?$select=SalesOrderID&$skip=3&$top=2", {
63861
+ value : [
63862
+ {SalesOrderID : "4"},
63863
+ {SalesOrderID : "5"}
63864
+ ]
63865
+ })
63866
+ .expectChange("id", [,,, "3", "4", "5"])
63867
+ .expectChange("selected", [,,, true, true, true]);
63868
+
63869
+ // code under test
63870
+ oTable.requestItems();
63871
+
63872
+ await this.waitForChanges(assert, "contexts created by paging are also selected");
63873
+
63874
+ this.expectChange("selectAll", false)
63875
+ .expectChange("selected", [false, false, false, false, false, false]);
62600
63876
 
62601
63877
  // code under test
62602
63878
  oHeaderContext.setSelected(false);
62603
63879
 
62604
63880
  checkSelected(assert, oHeaderContext, false);
62605
- await this.waitForChanges(assert);
63881
+ await this.waitForChanges(assert, "headerContext deselected via setSelected");
62606
63882
 
62607
- oSelectAllInput.setBindingContext(oContext);
63883
+ this.expectChange("selectAll", true); // for setBindingContext
62608
63884
 
62609
- // code under test - change listener is deregistered, no change expected
62610
- oHeaderContext.setSelected(true);
63885
+ const oNewListBinding = this.oModel.bindList("/SalesOrderList");
63886
+ oNewListBinding.getHeaderContext().setSelected(true);
63887
+ oSelectAllInput.setBindingContext(oNewListBinding.getHeaderContext());
62611
63888
 
62612
- await this.waitForChanges(assert);
63889
+ // code under test - no further change expected for "select all" binding
63890
+ oHeaderContext.setSelected(false);
63891
+
63892
+ await this.waitForChanges(assert, "swap context of property binding");
62613
63893
  });
62614
63894
 
62615
63895
  //*********************************************************************************************