robotframework-sapfx 0.8.2__tar.gz → 0.8.4__tar.gz

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 (184) hide show
  1. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/NOTICE +8 -3
  2. robotframework_sapfx-0.8.4/PKG-INFO +334 -0
  3. robotframework_sapfx-0.8.4/README.md +290 -0
  4. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/pyproject.toml +5 -60
  5. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/SapApiLibrary.py +87 -37
  6. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/__init__.py +1 -1
  7. robotframework_sapfx-0.8.4/src/SapApiLibrary/_bapi.py +158 -0
  8. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_discovery.py +128 -20
  9. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_http_security.py +22 -8
  10. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_odata_read.py +71 -14
  11. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_odata_write.py +57 -20
  12. robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc.py +325 -0
  13. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_rfc_extract.py +26 -11
  14. robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_idoc.py +360 -0
  15. robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_idoc_profiles.py +211 -0
  16. robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_idoc_wait.py +188 -0
  17. robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_jobs.py +318 -0
  18. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_rfc_reads.py +93 -35
  19. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_rfc_security.py +71 -18
  20. robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_spool.py +335 -0
  21. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_rfc_surface.py +52 -20
  22. robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_surface_artifact.py +115 -0
  23. robotframework_sapfx-0.8.4/src/SapApiLibrary/_xbp.py +158 -0
  24. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/SapEccLibrary.py +105 -114
  25. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/__init__.py +2 -2
  26. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/__init__.py +39 -9
  27. robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_abap_list.py +106 -0
  28. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_combobox.py +110 -18
  29. robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_connection.py +447 -0
  30. robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_connection_probe.py +130 -0
  31. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_ddic.py +81 -7
  32. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_diagnostics.py +61 -21
  33. robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_elements.py +282 -0
  34. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_embedded_browser.py +19 -11
  35. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_grid.py +132 -74
  36. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_grid_actions.py +101 -22
  37. robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_grid_cells.py +172 -0
  38. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_healing.py +18 -8
  39. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_identity.py +20 -4
  40. robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_inputs.py +252 -0
  41. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_menus.py +19 -4
  42. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_perception.py +101 -78
  43. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_pointer.py +18 -11
  44. robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_screenshots.py +365 -0
  45. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_se16.py +68 -16
  46. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_semantic.py +137 -37
  47. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_sessions.py +62 -21
  48. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_statusbar.py +15 -3
  49. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_table_control.py +59 -19
  50. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_tabstrip.py +26 -5
  51. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_toolbar.py +13 -3
  52. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_trees.py +177 -18
  53. robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_value_checks.py +80 -0
  54. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_visual.py +39 -20
  55. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_waits.py +152 -15
  56. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_watch.py +18 -13
  57. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_windows.py +119 -12
  58. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/SapFioriLibrary.py +7 -4
  59. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/__init__.py +1 -1
  60. robotframework_sapfx-0.8.4/src/SapFioriLibrary/_flp_js.py +156 -0
  61. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_capture.js.tpl +56 -12
  62. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_core.js.tpl +5 -0
  63. robotframework_sapfx-0.8.4/src/SapFioriLibrary/_ui5_bundle_dates.js.tpl +164 -0
  64. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_engines.js.tpl +1 -0
  65. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_js.py +12 -6
  66. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_runtime.py +25 -7
  67. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_spy_core.js.tpl +4 -1
  68. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_spy_exports.js.tpl +31 -7
  69. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_spy_record.js.tpl +29 -3
  70. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_spy_replay.js.tpl +6 -1
  71. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_webgui_js.py +1 -1
  72. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/__init__.py +4 -1
  73. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_actions.py +134 -18
  74. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_base.py +11 -7
  75. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_composition.py +18 -9
  76. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_engines.py +143 -48
  77. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_flp.py +56 -32
  78. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_flp_services.py +60 -24
  79. robotframework_sapfx-0.8.4/src/SapFioriLibrary/keywords/_flp_tile_refresh.py +191 -0
  80. robotframework_sapfx-0.8.4/src/SapFioriLibrary/keywords/_flp_tiles.py +340 -0
  81. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_frames.py +60 -29
  82. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_locators.py +120 -61
  83. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_perception.py +83 -42
  84. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_state.py +73 -37
  85. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_tables.py +18 -4
  86. robotframework_sapfx-0.8.4/src/robotframework_sapfx.egg-info/PKG-INFO +334 -0
  87. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/robotframework_sapfx.egg-info/SOURCES.txt +29 -2
  88. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/__init__.py +1 -1
  89. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/_semantic_match.py +47 -1
  90. robotframework_sapfx-0.8.4/src/sapfx_common/abap_components.py +71 -0
  91. robotframework_sapfx-0.8.4/src/sapfx_common/abap_list.py +256 -0
  92. robotframework_sapfx-0.8.4/src/sapfx_common/background_jobs.py +261 -0
  93. robotframework_sapfx-0.8.4/src/sapfx_common/bapi_return.py +146 -0
  94. robotframework_sapfx-0.8.4/src/sapfx_common/cds_source.py +232 -0
  95. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/com_safety.py +71 -2
  96. robotframework_sapfx-0.8.4/src/sapfx_common/flp_tiles.py +345 -0
  97. robotframework_sapfx-0.8.4/src/sapfx_common/idoc.py +377 -0
  98. robotframework_sapfx-0.8.4/src/sapfx_common/idoc_profiles.py +198 -0
  99. robotframework_sapfx-0.8.4/src/sapfx_common/idoc_status.py +199 -0
  100. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/odata_metadata.py +20 -2
  101. robotframework_sapfx-0.8.4/src/sapfx_common/rap_preview.py +161 -0
  102. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/rfc_channel.py +4 -2
  103. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/rfc_extract.py +47 -13
  104. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/rfc_reads.py +62 -0
  105. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/rfc_tables.py +42 -0
  106. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/semantic.py +36 -15
  107. robotframework_sapfx-0.8.4/src/sapfx_common/spool.py +312 -0
  108. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_control.py +28 -0
  109. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/tree_nodes.py +18 -0
  110. robotframework_sapfx-0.8.4/src/sapfx_common/ui5_dates.py +117 -0
  111. robotframework_sapfx-0.8.4/src/sapfx_common/vkeys.py +83 -0
  112. robotframework_sapfx-0.8.2/PKG-INFO +0 -400
  113. robotframework_sapfx-0.8.2/README.md +0 -355
  114. robotframework_sapfx-0.8.2/src/SapApiLibrary/_rfc.py +0 -482
  115. robotframework_sapfx-0.8.2/src/SapEccLibrary/_vendor/__init__.py +0 -4
  116. robotframework_sapfx-0.8.2/src/SapEccLibrary/_vendor/sapgui_base.py +0 -791
  117. robotframework_sapfx-0.8.2/src/SapEccLibrary/keywords/_connection.py +0 -253
  118. robotframework_sapfx-0.8.2/src/SapEccLibrary/keywords/_screenshots.py +0 -206
  119. robotframework_sapfx-0.8.2/src/robotframework_sapfx.egg-info/PKG-INFO +0 -400
  120. robotframework_sapfx-0.8.2/src/sapfx_common/abap_list.py +0 -48
  121. robotframework_sapfx-0.8.2/src/sapfx_common/bapi_return.py +0 -64
  122. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/LICENSE +0 -0
  123. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/setup.cfg +0 -0
  124. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_core.py +0 -0
  125. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_http.py +0 -0
  126. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/py.typed +0 -0
  127. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/py.typed +0 -0
  128. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_info.js.tpl +0 -0
  129. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_shadow.js.tpl +0 -0
  130. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_tables.js.tpl +0 -0
  131. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_webgui_grid.js.tpl +0 -0
  132. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_webgui_selection.js.tpl +0 -0
  133. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/py.typed +0 -0
  134. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/regen_recorder.py +0 -0
  135. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/robotframework_sapfx.egg-info/dependency_links.txt +0 -0
  136. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/robotframework_sapfx.egg-info/requires.txt +0 -0
  137. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/robotframework_sapfx.egg-info/top_level.txt +0 -0
  138. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/_cross_channel_artifact.py +0 -0
  139. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/_cross_channel_contract.py +0 -0
  140. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/_tabular.py +0 -0
  141. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/_tabular_io.py +0 -0
  142. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/alv_cells.py +0 -0
  143. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/artifacts.py +0 -0
  144. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/auth_flows.py +0 -0
  145. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/client_security.py +0 -0
  146. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/combo_box.py +0 -0
  147. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/cross_channel.py +0 -0
  148. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/ddic_inventory.py +0 -0
  149. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/fiori_diagnostics.py +0 -0
  150. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/gateway_status.py +0 -0
  151. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/healing.py +0 -0
  152. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/healing_telemetry.py +0 -0
  153. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/http_security.py +0 -0
  154. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/menu_path.py +0 -0
  155. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/object_tree.py +0 -0
  156. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/odata_batch.py +0 -0
  157. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/parameter_origin.py +0 -0
  158. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/perception_diff.py +0 -0
  159. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/polling.py +0 -0
  160. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/py.typed +0 -0
  161. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/rfc_surface.py +0 -0
  162. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/robot_args.py +0 -0
  163. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/screen_watch.py +0 -0
  164. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/secrets.py +0 -0
  165. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/security_baseline.py +0 -0
  166. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/security_inventory.py +0 -0
  167. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/security_surface.py +0 -0
  168. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/session_context.py +0 -0
  169. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/status_message.py +0 -0
  170. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/system_identity.py +0 -0
  171. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/tab_strip.py +0 -0
  172. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_csv.py +0 -0
  173. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_extract.py +0 -0
  174. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_json.py +0 -0
  175. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_parquet.py +0 -0
  176. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_svg.py +0 -0
  177. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_xlsx.py +0 -0
  178. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/user_formats.py +0 -0
  179. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/visual_baseline.py +0 -0
  180. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/visual_hash.py +0 -0
  181. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/vocabulary.py +0 -0
  182. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/web_cookies.py +0 -0
  183. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/webgui_selection.py +0 -0
  184. {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/write_simulation.py +0 -0
@@ -8,9 +8,14 @@ This product includes software developed as part of:
8
8
  https://github.com/frankvanderkuur/robotframework-sapguilibrary
9
9
  Licensed under the Apache License, Version 2.0.
10
10
 
11
- The file `src/SapEccLibrary/_vendor/sapgui_base.py` is a vendored copy of that
12
- project's `SapGuiLibrary.py`, with the single modification of renaming the class
13
- `SapGuiLibrary` to `SapGuiBase`. See that file's header for details.
11
+ Parts of `src/SapEccLibrary/` derive from that project's `SapGuiLibrary.py`
12
+ (version 1.2.1). That file was first included verbatim, then absorbed and
13
+ rewritten on 2026-10-06 into this project's own modules, keeping the names and
14
+ signatures of its 37 keywords: `keywords/_connection.py`, `_elements.py`,
15
+ `_inputs.py`, `_value_checks.py`, `_grid_cells.py`, `_grid_actions.py`,
16
+ `_trees.py`, `_screenshots.py` and `_waits.py`, and the virtual-key table of
17
+ `src/sapfx_common/vkeys.py`. Each of those files states the derivation in its
18
+ header.
14
19
 
15
20
  ----------------------------------------------------------------------
16
21
 
@@ -0,0 +1,334 @@
1
+ Metadata-Version: 2.4
2
+ Name: robotframework-sapfx
3
+ Version: 0.8.4
4
+ Summary: SAPFX - SAP test automation for Robot Framework: SAP GUI (ECC / S4 backend), Fiori/UI5, OData API.
5
+ Author-email: Cyril Montiel <cyril@montiel.me>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/CyrilM29/robotframework-sapfx
8
+ Project-URL: Documentation, https://cyrilm29.github.io/robotframework-sapfx/
9
+ Keywords: robotframework,robot-framework,test-automation,testing,qa,sap,sapgui,sap-gui,ecc,s4hana,abap,fiori,sapui5,ui5,playwright,odata,rfc,bapi,api-testing,self-healing,mcp,ai-agents
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Information Technology
13
+ Classifier: Framework :: Robot Framework
14
+ Classifier: Framework :: Robot Framework :: Library
15
+ Classifier: Topic :: Software Development :: Testing
16
+ Classifier: Topic :: Software Development :: Testing :: Acceptance
17
+ Classifier: Topic :: Software Development :: Quality Assurance
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Operating System :: Microsoft :: Windows
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ License-File: NOTICE
29
+ Requires-Dist: robotframework>=7.4
30
+ Requires-Dist: pywin32>=305; platform_system == "Windows"
31
+ Provides-Extra: web
32
+ Requires-Dist: robotframework-browser<21,>=20.0; extra == "web"
33
+ Provides-Extra: visual
34
+ Requires-Dist: Pillow>=10.0; extra == "visual"
35
+ Provides-Extra: parquet
36
+ Requires-Dist: pyarrow>=14.0; extra == "parquet"
37
+ Provides-Extra: dev
38
+ Requires-Dist: pytest>=7.0; extra == "dev"
39
+ Requires-Dist: pytest-cov>=5.0; extra == "dev"
40
+ Requires-Dist: ruff>=0.4; extra == "dev"
41
+ Requires-Dist: pre-commit>=3.0; extra == "dev"
42
+ Requires-Dist: mypy>=1.10; extra == "dev"
43
+ Dynamic: license-file
44
+
45
+ <p align="center">
46
+ <img src="https://raw.githubusercontent.com/CyrilM29/robotframework-sapfx/main/assets/logo-library.png" alt="SAPFX: ECC UI5 API Library" width="240">
47
+ </p>
48
+
49
+ # SAPFX: Robot Framework libraries for testing SAP
50
+
51
+ [![PyPI](https://img.shields.io/pypi/v/robotframework-sapfx)](https://pypi.org/project/robotframework-sapfx/)
52
+ [![Python](https://img.shields.io/pypi/pyversions/robotframework-sapfx)](https://pypi.org/project/robotframework-sapfx/)
53
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](https://github.com/CyrilM29/robotframework-sapfx/blob/main/LICENSE)
54
+
55
+ ```bash
56
+ pip install robotframework-sapfx
57
+ ```
58
+
59
+ SAPFX automates SAP tests in Robot Framework through **three libraries, one per
60
+ channel**: the SAP GUI desktop client, SAP Fiori and SAPUI5 apps in the browser,
61
+ and the OData/RFC API channel. Each keeps the locators of its technology (a SAP
62
+ GUI scripting id, a UI5 control selector, an OData entity set); what they share
63
+ is **the same contracts and the same method**: one completeness rule for
64
+ extracting a table, whether it comes from an ALV grid, a UI5 table or an RFC
65
+ call; one message identity (`MO/E/402`) on the screen and over RFC; and, on the
66
+ two screen channels, the same perception → action loop and one locator-repair
67
+ log. The business vocabulary is built above, in your project's Robot Framework
68
+ keywords: that is where a test stops depending on the channel. One run can
69
+ cross all three (prepare data through the API, drive
70
+ the screen for what you actually test, check the result through another
71
+ channel). Because they also write, delete and cross-check their own writes
72
+ through two channels, the same libraries are heading beyond testing, towards
73
+ test data, populated databases and controlled loads (see
74
+ "Beyond testing" below for what is proven and what is not yet).
75
+
76
+ This repository publishes the **library sources**, their **documentation** and
77
+ the **keyword reference**. The libraries are distributed on PyPI as
78
+ `robotframework-sapfx`.
79
+
80
+ | Library | Channel | Driven through |
81
+ | --- | --- | --- |
82
+ | **`SapEccLibrary`** | SAP GUI for Windows (ECC, S/4HANA backend) | SAP GUI Scripting API over COM (`pywin32`). Drop-in compatible with [robotframework-sapguilibrary](https://github.com/frankvanderkuur/robotframework-sapguilibrary): each of its keywords keeps its name and signature, a few now fail loudly where it returned a misleading value. |
83
+ | **`SapFioriLibrary`** | SAP Fiori / SAPUI5, UI5 Web Components, SAP GUI for HTML | The [Browser library](https://github.com/MarketSquare/robotframework-browser) (Playwright), with **UI5-stable control selectors** instead of generated DOM ids. Locator engine ported from [playwright-sap](https://github.com/ArpitSureka/playwright-sap). |
84
+ | **`SapApiLibrary`** | OData v2 and v4, RFC / BAPI | Python standard library for HTTP (SAP CSRF protocol included); optional RFC through `pyrfc`. |
85
+
86
+ A fourth package, `sapfx_common`, holds the pure logic the three share
87
+ (polling, healing scores, perception diff, human-locator engine, table
88
+ extraction contract, visual hashing...). Some of its modules are Robot
89
+ libraries in their own right, documented in their docstrings rather than in
90
+ the keyword reference: `Library sapfx_common.table_csv` (also `table_json`,
91
+ `table_xlsx`, `table_svg`, `table_parquet`) writes an extraction and reads it
92
+ back, `sapfx_common.table_extract` carries the shared
93
+ `Table Extract Should Be Complete` guard, `sapfx_common.artifacts` writes and
94
+ re-reads deterministic JSON artifacts, and `sapfx_common.rap_preview` builds
95
+ the Fiori Elements preview path of a RAP service.
96
+
97
+ 📖 **[Keyword documentation](https://cyrilm29.github.io/robotframework-sapfx/)**:
98
+ one reference page per library, every keyword with its arguments and examples.
99
+
100
+ ## Install
101
+
102
+ ```bash
103
+ pip install robotframework-sapfx # the three libraries
104
+ pip install "robotframework-sapfx[web]" # + Browser library, for SapFioriLibrary
105
+ rfbrowser init # one-time: Playwright browsers
106
+ ```
107
+
108
+ Other extras: `visual` (Pillow, for screen baselines) and `parquet` (pyarrow,
109
+ for Parquet exports). Requirements per channel:
110
+
111
+ - **All**: Python 3.10 or later, Robot Framework 7.4 or later.
112
+ - **`SapEccLibrary`**: Windows, SAP GUI for Windows, and scripting enabled on
113
+ the server (RZ11 `sapgui/user_scripting`) and on the client.
114
+ `Scripting Should Be Fully Enabled` checks both and names the parameter to
115
+ fix. Pin `pywin32` exactly in your environment file: it is the first source
116
+ of COM breakage.
117
+ - **`SapFioriLibrary`**: the `web` extra and `rfbrowser init`. No SAP system is
118
+ needed to try it: the public OpenUI5 Demo Kit is a valid target.
119
+ - **RFC in `SapApiLibrary`** (optional): `pyrfc`, pinned
120
+ (`pip install pyrfc==3.3.1`: SAP archived the project and every PyPI release
121
+ is yanked, so pip no longer picks one by itself; prebuilt wheels up to
122
+ Python 3.12 only), and the SAP NW RFC runtime, which a SAP GUI for
123
+ Windows 8.00 installation usually provides already (component "SAP NWRFC
124
+ x64 Shared"). Without it, the RFC keywords say so and the rest of the
125
+ library works.
126
+
127
+ A free local SAP system to test against (ABAP Platform Trial in Docker), and
128
+ the SAP-side prerequisites, are described in
129
+ [docs/testing-without-sap.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/testing-without-sap.md).
130
+
131
+ ## Quick start
132
+
133
+ **SAP GUI** (credentials on the command line:
134
+ `robot -v "PASSWORD: Secret:..." suite.robot`; the Robot Framework 7.4 typed
135
+ variable keeps the password out of the logs, even at TRACE level):
136
+
137
+ ```robotframework
138
+ *** Settings ***
139
+ Library SapEccLibrary
140
+
141
+ *** Variables ***
142
+ ${CONNECTION} MY SYSTEM
143
+ ${USER} DEVELOPER
144
+ ${PASSWORD} ${EMPTY}
145
+ ${GRID} wnd[0]/usr/cntlGRID1/shellcont/shell
146
+
147
+ *** Test Cases ***
148
+ Read The Clients Table In SE16
149
+ Open Sap Logon
150
+ Connect To Session With Retry
151
+ Open Connection ${CONNECTION}
152
+ Input Text wnd[0]/usr/txtRSYST-BNAME ${USER}
153
+ Input Password wnd[0]/usr/pwdRSYST-BCODE ${PASSWORD}
154
+ Send Vkey 0
155
+ Scripting Should Be Fully Enabled
156
+ Use ALV Grid In Data Browser
157
+ Input Text wnd[0]/usr/ctxtDATABROWSE-TABLENAME T000
158
+ Send Vkey 0
159
+ Send Vkey 8
160
+ ${rows}= Read Full Grid ${GRID}
161
+ Log ${rows}
162
+ ```
163
+
164
+ In a real project, the SAP element ids live in a resource file of business
165
+ keywords, and the test cases speak business language only.
166
+
167
+ **SAP Fiori / SAPUI5** (runs as is against the public OpenUI5 Demo Kit):
168
+
169
+ ```robotframework
170
+ *** Settings ***
171
+ Library Browser
172
+ Library SapFioriLibrary ui5_timeout=20s
173
+
174
+ *** Test Cases ***
175
+ Search The API Reference
176
+ New Browser chromium headless=True
177
+ New Page https://sdk.openui5.org/#/api
178
+ Fill Ui5 Input Button controlType=SearchField
179
+ ${xpath}= Get Ui5 Xpath controlType=SearchField
180
+ Log ${xpath}
181
+ [Teardown] Close Browser
182
+ ```
183
+
184
+ **OData** (a SAP Gateway service, here the EPM demo shop of the ABAP trial):
185
+
186
+ ```robotframework
187
+ *** Settings ***
188
+ Library SapApiLibrary
189
+
190
+ *** Variables ***
191
+ ${PASSWORD} ${EMPTY}
192
+
193
+ *** Test Cases ***
194
+ Count The Products
195
+ Open Api Session http://localhost:50000 user=DEVELOPER
196
+ ... password=${PASSWORD} sap_client=001
197
+ ${count}= Get Odata Count /sap/opu/odata/sap/SEPMRA_SHOP/Products
198
+ Should Be True ${count} > 0
199
+ ${first}= Get Odata Entities /sap/opu/odata/sap/SEPMRA_SHOP/Products top=3
200
+ Length Should Be ${first} 3
201
+ [Teardown] Close All Api Sessions
202
+ ```
203
+
204
+ ## What the libraries bring
205
+
206
+ - **Real synchronisation**, never fixed sleeps: `Wait Until Busy Done`,
207
+ `Wait Until Element Present` (SAP GUI), `Wait For Ui5 Idle` (network,
208
+ busy indicators and a continuous quiet period, on UI5 and non-UI5 pages).
209
+ - **Locale-independent assertions**: `Run Transaction` judges the status-bar
210
+ message **type**, never its translated text; `Get Status Message Identity`
211
+ reads class, type and number; `Ui5 Should Have No Messages Of Type` does the
212
+ same on the web. Dates and numbers are typed in the user's own format
213
+ (`Input Date`, `Input Number`, `Fill Ui5 Date`), and a screen's display or
214
+ change mode is read from a field (`Element Should Be Changeable`), never from
215
+ its translated title.
216
+ - **Tables read as data**: ALV grids by column title (`Read Grid`,
217
+ `Read Full Grid`, `Get Grid Column Titles`), table controls, trees, classic
218
+ ABAP lists, UI5 tables and SAP GUI for HTML grids; one extraction contract for
219
+ all channels, which refuses a partial reading instead of passing it for a
220
+ complete one, and five export formats (CSV, JSON Lines, XLSX, SVG, Parquet).
221
+ - **Human locators** (SAP GUI): `Fill Field By Label`, `Click Button By Label`,
222
+ `Read Field By Label`, by visible label and geometry; an ambiguity is always
223
+ reported with its candidates, never resolved by a silent first match.
224
+ - **Five resolution engines on the web**: UI5 `role` and hierarchical `xpath`
225
+ (`//Table//Button[@text='Edit']`), `sid` for SAP GUI for HTML, `wc` for UI5
226
+ Web Components pages without a classic runtime, and `dom` (ARIA role and
227
+ accessible name) for the non-SAP parts of hybrid pages; nested iframes of
228
+ launchpads through a frame stack; `Get Page Composition` says which
229
+ technology lives where.
230
+ - **Locator healing, never silent**: failures list the closest ids on screen,
231
+ scored; `Resolve Element With Healing` and `Resolve Ui5 With Fallback` repair
232
+ a stale locator with a logged warning and an optional telemetry journal.
233
+ - **Screen perception** for debugging and AI agents: `Get Screen Signature`,
234
+ `Get Screen Map` (numbered actionable targets), `Get Ui5 Page Tree`, diff
235
+ mode, annotated screenshots.
236
+ - **Visual assertions** where the Scripting API sees nothing (opaque shells,
237
+ charts): perceptual-hash baselines per screen, per element or per tile.
238
+ - **Preflights** that name their remedy: scripting on server and client,
239
+ workstation security posture, Gateway activation, RFC channel availability;
240
+ and the ABAP server's security configuration read over RFC (profile
241
+ parameters judged on their return code, drift against a committed
242
+ reference).
243
+ - **The API channel as a data platform**: full OData CRUD with CSRF, `$batch`,
244
+ server-driven paging, `$metadata` perception with human labels, a test-data
245
+ factory that cleans up after itself, BAPIs judged by message type and
246
+ refusals asserted by message identifier, RFC table reads, background jobs
247
+ and their spool, outbound IDocs (create, wait on the status code, link to
248
+ the inbound IDoc by its TID), change documents.
249
+ - **Several SAP GUI sessions** by alias in one suite, SAP Fiori launchpad
250
+ navigation by intent and login through an identity provider, tile counters
251
+ read as numbers (`Get Flp Tile Counter`), and identity readings (release,
252
+ kernel, client; over HTTP alone with `Get Abap Software Components`) that
253
+ prove which system a test is really talking to.
254
+
255
+ Teams that test UI5 apps with JavaScript tooling will know
256
+ [wdi5](https://github.com/ui5-community/wdi5), the reference outside Robot
257
+ Framework. SAPFX does not replace it: its scope is SAP test automation in Robot
258
+ Framework, where the desktop client, the API channel and Fiori share one
259
+ runner, one report and the same contracts.
260
+
261
+ ## Beyond testing
262
+
263
+ The libraries were built to test SAP, and that stays their core. What makes a
264
+ test trustworthy (write a record through one channel, read it back through
265
+ another, independent one, delete it, and confirm it is gone) also works outside
266
+ a test. Three uses follow from it:
267
+
268
+ - **Test data sets**: creating complete, consistent data sets, identifiable as
269
+ test data, to feed test campaigns.
270
+ - **Populating databases for performance testing**: filling empty or incomplete
271
+ SAP databases before a load campaign.
272
+ - **Configuration and migration loads**: loading complex business data into a
273
+ target environment, and cross-checking the load through a second channel, for
274
+ instance in an ECC to S/4HANA migration.
275
+
276
+ To be precise about where this stands: writing, deleting and cross-checking
277
+ through two channels are validated live on SAP development systems, never on a
278
+ customer system. The three uses themselves are a direction, not delivered
279
+ features. There is no data-set generator in the libraries yet, no volume or load
280
+ time has been measured, and no migration has been run. The angle for migrations
281
+ is scripted loading plus cross-checking, not replacing SAP's own load and
282
+ migration tools.
283
+
284
+ ## Documentation
285
+
286
+ | Document | Topic |
287
+ | --- | --- |
288
+ | [Keyword reference](https://cyrilm29.github.io/robotframework-sapfx/) | Every keyword of the three libraries |
289
+ | [docs/architecture.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/architecture.md) | How the libraries are built and how they fit together |
290
+ | [docs/fiori-architecture.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/fiori-architecture.md) | The web side: UI5 selectors, engines, frames, hybrid pages |
291
+ | [docs/testing-without-sap.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/testing-without-sap.md) | A free local SAP system, SAP-side prerequisites |
292
+ | [docs/sap-test-data.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/sap-test-data.md) | Test data and targets available without a customer system |
293
+ | [docs/ecc-validation.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/ecc-validation.md) | Validation against a live ABAP system, step by step |
294
+ | [docs/hardening-test-environment.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/hardening-test-environment.md) | Security checklist for the server, the workstation and the web side |
295
+ | [docs/migrating-from-sapguilibrary.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/migrating-from-sapguilibrary.md) | Moving from robotframework-sapguilibrary |
296
+ | [docs/migrating-from-cbta.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/migrating-from-cbta.md) | Moving from SAP CBTA |
297
+ | [docs/audit-upstream.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/audit-upstream.md) | What SapEccLibrary changes in the upstream code it embeds, and why |
298
+
299
+ Every document exists in English and in French (`*.fr.md`). They were written
300
+ alongside the libraries in the maintainer's workbench: when they mention a
301
+ business resource layer (`resources/`), Robot suites (`tests/robot/`),
302
+ recorders or test agents, they describe that workbench, which is not part of
303
+ this repository.
304
+
305
+ ## Layout
306
+
307
+ ```text
308
+ src/SapEccLibrary/ SAP GUI for Windows (COM); keywords/ one mixin per
309
+ capability, robotframework-sapguilibrary's included
310
+ src/SapFioriLibrary/ Fiori / UI5 / Web Components / SAP GUI for HTML
311
+ (Browser library); injected JavaScript in *.js.tpl
312
+ src/SapApiLibrary/ OData v2/v4 and optional RFC / BAPI
313
+ src/sapfx_common/ shared pure logic
314
+ docs/ library documentation (EN/FR), docs/libdoc/ = keyword pages
315
+ ```
316
+
317
+ ## Issues
318
+
319
+ Bug reports and suggestions are welcome as
320
+ [GitHub issues](https://github.com/CyrilM29/robotframework-sapfx/issues).
321
+
322
+ ## License
323
+
324
+ Apache 2.0. Includes code absorbed from robotframework-sapguilibrary, locator
325
+ engines ported from playwright-sap and techniques adapted from RoboSAPiens and
326
+ playwright-praman; see [LICENSE](https://github.com/CyrilM29/robotframework-sapfx/blob/main/LICENSE) and [NOTICE](https://github.com/CyrilM29/robotframework-sapfx/blob/main/NOTICE).
327
+
328
+ ## Trademarks
329
+
330
+ SAP, SAP ECC, SAP S/4HANA, SAP Fiori, SAP BTP, SAP HANA, SAP NetWeaver, SAP
331
+ GUI, SAPUI5, ABAP and the other SAP products and services mentioned are
332
+ trademarks or registered trademarks of SAP SE or its affiliates in Germany and
333
+ in other countries. SAPFX is an independent open-source project, not affiliated
334
+ with, sponsored or endorsed by SAP SE.
@@ -0,0 +1,290 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/CyrilM29/robotframework-sapfx/main/assets/logo-library.png" alt="SAPFX: ECC UI5 API Library" width="240">
3
+ </p>
4
+
5
+ # SAPFX: Robot Framework libraries for testing SAP
6
+
7
+ [![PyPI](https://img.shields.io/pypi/v/robotframework-sapfx)](https://pypi.org/project/robotframework-sapfx/)
8
+ [![Python](https://img.shields.io/pypi/pyversions/robotframework-sapfx)](https://pypi.org/project/robotframework-sapfx/)
9
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](https://github.com/CyrilM29/robotframework-sapfx/blob/main/LICENSE)
10
+
11
+ ```bash
12
+ pip install robotframework-sapfx
13
+ ```
14
+
15
+ SAPFX automates SAP tests in Robot Framework through **three libraries, one per
16
+ channel**: the SAP GUI desktop client, SAP Fiori and SAPUI5 apps in the browser,
17
+ and the OData/RFC API channel. Each keeps the locators of its technology (a SAP
18
+ GUI scripting id, a UI5 control selector, an OData entity set); what they share
19
+ is **the same contracts and the same method**: one completeness rule for
20
+ extracting a table, whether it comes from an ALV grid, a UI5 table or an RFC
21
+ call; one message identity (`MO/E/402`) on the screen and over RFC; and, on the
22
+ two screen channels, the same perception → action loop and one locator-repair
23
+ log. The business vocabulary is built above, in your project's Robot Framework
24
+ keywords: that is where a test stops depending on the channel. One run can
25
+ cross all three (prepare data through the API, drive
26
+ the screen for what you actually test, check the result through another
27
+ channel). Because they also write, delete and cross-check their own writes
28
+ through two channels, the same libraries are heading beyond testing, towards
29
+ test data, populated databases and controlled loads (see
30
+ "Beyond testing" below for what is proven and what is not yet).
31
+
32
+ This repository publishes the **library sources**, their **documentation** and
33
+ the **keyword reference**. The libraries are distributed on PyPI as
34
+ `robotframework-sapfx`.
35
+
36
+ | Library | Channel | Driven through |
37
+ | --- | --- | --- |
38
+ | **`SapEccLibrary`** | SAP GUI for Windows (ECC, S/4HANA backend) | SAP GUI Scripting API over COM (`pywin32`). Drop-in compatible with [robotframework-sapguilibrary](https://github.com/frankvanderkuur/robotframework-sapguilibrary): each of its keywords keeps its name and signature, a few now fail loudly where it returned a misleading value. |
39
+ | **`SapFioriLibrary`** | SAP Fiori / SAPUI5, UI5 Web Components, SAP GUI for HTML | The [Browser library](https://github.com/MarketSquare/robotframework-browser) (Playwright), with **UI5-stable control selectors** instead of generated DOM ids. Locator engine ported from [playwright-sap](https://github.com/ArpitSureka/playwright-sap). |
40
+ | **`SapApiLibrary`** | OData v2 and v4, RFC / BAPI | Python standard library for HTTP (SAP CSRF protocol included); optional RFC through `pyrfc`. |
41
+
42
+ A fourth package, `sapfx_common`, holds the pure logic the three share
43
+ (polling, healing scores, perception diff, human-locator engine, table
44
+ extraction contract, visual hashing...). Some of its modules are Robot
45
+ libraries in their own right, documented in their docstrings rather than in
46
+ the keyword reference: `Library sapfx_common.table_csv` (also `table_json`,
47
+ `table_xlsx`, `table_svg`, `table_parquet`) writes an extraction and reads it
48
+ back, `sapfx_common.table_extract` carries the shared
49
+ `Table Extract Should Be Complete` guard, `sapfx_common.artifacts` writes and
50
+ re-reads deterministic JSON artifacts, and `sapfx_common.rap_preview` builds
51
+ the Fiori Elements preview path of a RAP service.
52
+
53
+ 📖 **[Keyword documentation](https://cyrilm29.github.io/robotframework-sapfx/)**:
54
+ one reference page per library, every keyword with its arguments and examples.
55
+
56
+ ## Install
57
+
58
+ ```bash
59
+ pip install robotframework-sapfx # the three libraries
60
+ pip install "robotframework-sapfx[web]" # + Browser library, for SapFioriLibrary
61
+ rfbrowser init # one-time: Playwright browsers
62
+ ```
63
+
64
+ Other extras: `visual` (Pillow, for screen baselines) and `parquet` (pyarrow,
65
+ for Parquet exports). Requirements per channel:
66
+
67
+ - **All**: Python 3.10 or later, Robot Framework 7.4 or later.
68
+ - **`SapEccLibrary`**: Windows, SAP GUI for Windows, and scripting enabled on
69
+ the server (RZ11 `sapgui/user_scripting`) and on the client.
70
+ `Scripting Should Be Fully Enabled` checks both and names the parameter to
71
+ fix. Pin `pywin32` exactly in your environment file: it is the first source
72
+ of COM breakage.
73
+ - **`SapFioriLibrary`**: the `web` extra and `rfbrowser init`. No SAP system is
74
+ needed to try it: the public OpenUI5 Demo Kit is a valid target.
75
+ - **RFC in `SapApiLibrary`** (optional): `pyrfc`, pinned
76
+ (`pip install pyrfc==3.3.1`: SAP archived the project and every PyPI release
77
+ is yanked, so pip no longer picks one by itself; prebuilt wheels up to
78
+ Python 3.12 only), and the SAP NW RFC runtime, which a SAP GUI for
79
+ Windows 8.00 installation usually provides already (component "SAP NWRFC
80
+ x64 Shared"). Without it, the RFC keywords say so and the rest of the
81
+ library works.
82
+
83
+ A free local SAP system to test against (ABAP Platform Trial in Docker), and
84
+ the SAP-side prerequisites, are described in
85
+ [docs/testing-without-sap.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/testing-without-sap.md).
86
+
87
+ ## Quick start
88
+
89
+ **SAP GUI** (credentials on the command line:
90
+ `robot -v "PASSWORD: Secret:..." suite.robot`; the Robot Framework 7.4 typed
91
+ variable keeps the password out of the logs, even at TRACE level):
92
+
93
+ ```robotframework
94
+ *** Settings ***
95
+ Library SapEccLibrary
96
+
97
+ *** Variables ***
98
+ ${CONNECTION} MY SYSTEM
99
+ ${USER} DEVELOPER
100
+ ${PASSWORD} ${EMPTY}
101
+ ${GRID} wnd[0]/usr/cntlGRID1/shellcont/shell
102
+
103
+ *** Test Cases ***
104
+ Read The Clients Table In SE16
105
+ Open Sap Logon
106
+ Connect To Session With Retry
107
+ Open Connection ${CONNECTION}
108
+ Input Text wnd[0]/usr/txtRSYST-BNAME ${USER}
109
+ Input Password wnd[0]/usr/pwdRSYST-BCODE ${PASSWORD}
110
+ Send Vkey 0
111
+ Scripting Should Be Fully Enabled
112
+ Use ALV Grid In Data Browser
113
+ Input Text wnd[0]/usr/ctxtDATABROWSE-TABLENAME T000
114
+ Send Vkey 0
115
+ Send Vkey 8
116
+ ${rows}= Read Full Grid ${GRID}
117
+ Log ${rows}
118
+ ```
119
+
120
+ In a real project, the SAP element ids live in a resource file of business
121
+ keywords, and the test cases speak business language only.
122
+
123
+ **SAP Fiori / SAPUI5** (runs as is against the public OpenUI5 Demo Kit):
124
+
125
+ ```robotframework
126
+ *** Settings ***
127
+ Library Browser
128
+ Library SapFioriLibrary ui5_timeout=20s
129
+
130
+ *** Test Cases ***
131
+ Search The API Reference
132
+ New Browser chromium headless=True
133
+ New Page https://sdk.openui5.org/#/api
134
+ Fill Ui5 Input Button controlType=SearchField
135
+ ${xpath}= Get Ui5 Xpath controlType=SearchField
136
+ Log ${xpath}
137
+ [Teardown] Close Browser
138
+ ```
139
+
140
+ **OData** (a SAP Gateway service, here the EPM demo shop of the ABAP trial):
141
+
142
+ ```robotframework
143
+ *** Settings ***
144
+ Library SapApiLibrary
145
+
146
+ *** Variables ***
147
+ ${PASSWORD} ${EMPTY}
148
+
149
+ *** Test Cases ***
150
+ Count The Products
151
+ Open Api Session http://localhost:50000 user=DEVELOPER
152
+ ... password=${PASSWORD} sap_client=001
153
+ ${count}= Get Odata Count /sap/opu/odata/sap/SEPMRA_SHOP/Products
154
+ Should Be True ${count} > 0
155
+ ${first}= Get Odata Entities /sap/opu/odata/sap/SEPMRA_SHOP/Products top=3
156
+ Length Should Be ${first} 3
157
+ [Teardown] Close All Api Sessions
158
+ ```
159
+
160
+ ## What the libraries bring
161
+
162
+ - **Real synchronisation**, never fixed sleeps: `Wait Until Busy Done`,
163
+ `Wait Until Element Present` (SAP GUI), `Wait For Ui5 Idle` (network,
164
+ busy indicators and a continuous quiet period, on UI5 and non-UI5 pages).
165
+ - **Locale-independent assertions**: `Run Transaction` judges the status-bar
166
+ message **type**, never its translated text; `Get Status Message Identity`
167
+ reads class, type and number; `Ui5 Should Have No Messages Of Type` does the
168
+ same on the web. Dates and numbers are typed in the user's own format
169
+ (`Input Date`, `Input Number`, `Fill Ui5 Date`), and a screen's display or
170
+ change mode is read from a field (`Element Should Be Changeable`), never from
171
+ its translated title.
172
+ - **Tables read as data**: ALV grids by column title (`Read Grid`,
173
+ `Read Full Grid`, `Get Grid Column Titles`), table controls, trees, classic
174
+ ABAP lists, UI5 tables and SAP GUI for HTML grids; one extraction contract for
175
+ all channels, which refuses a partial reading instead of passing it for a
176
+ complete one, and five export formats (CSV, JSON Lines, XLSX, SVG, Parquet).
177
+ - **Human locators** (SAP GUI): `Fill Field By Label`, `Click Button By Label`,
178
+ `Read Field By Label`, by visible label and geometry; an ambiguity is always
179
+ reported with its candidates, never resolved by a silent first match.
180
+ - **Five resolution engines on the web**: UI5 `role` and hierarchical `xpath`
181
+ (`//Table//Button[@text='Edit']`), `sid` for SAP GUI for HTML, `wc` for UI5
182
+ Web Components pages without a classic runtime, and `dom` (ARIA role and
183
+ accessible name) for the non-SAP parts of hybrid pages; nested iframes of
184
+ launchpads through a frame stack; `Get Page Composition` says which
185
+ technology lives where.
186
+ - **Locator healing, never silent**: failures list the closest ids on screen,
187
+ scored; `Resolve Element With Healing` and `Resolve Ui5 With Fallback` repair
188
+ a stale locator with a logged warning and an optional telemetry journal.
189
+ - **Screen perception** for debugging and AI agents: `Get Screen Signature`,
190
+ `Get Screen Map` (numbered actionable targets), `Get Ui5 Page Tree`, diff
191
+ mode, annotated screenshots.
192
+ - **Visual assertions** where the Scripting API sees nothing (opaque shells,
193
+ charts): perceptual-hash baselines per screen, per element or per tile.
194
+ - **Preflights** that name their remedy: scripting on server and client,
195
+ workstation security posture, Gateway activation, RFC channel availability;
196
+ and the ABAP server's security configuration read over RFC (profile
197
+ parameters judged on their return code, drift against a committed
198
+ reference).
199
+ - **The API channel as a data platform**: full OData CRUD with CSRF, `$batch`,
200
+ server-driven paging, `$metadata` perception with human labels, a test-data
201
+ factory that cleans up after itself, BAPIs judged by message type and
202
+ refusals asserted by message identifier, RFC table reads, background jobs
203
+ and their spool, outbound IDocs (create, wait on the status code, link to
204
+ the inbound IDoc by its TID), change documents.
205
+ - **Several SAP GUI sessions** by alias in one suite, SAP Fiori launchpad
206
+ navigation by intent and login through an identity provider, tile counters
207
+ read as numbers (`Get Flp Tile Counter`), and identity readings (release,
208
+ kernel, client; over HTTP alone with `Get Abap Software Components`) that
209
+ prove which system a test is really talking to.
210
+
211
+ Teams that test UI5 apps with JavaScript tooling will know
212
+ [wdi5](https://github.com/ui5-community/wdi5), the reference outside Robot
213
+ Framework. SAPFX does not replace it: its scope is SAP test automation in Robot
214
+ Framework, where the desktop client, the API channel and Fiori share one
215
+ runner, one report and the same contracts.
216
+
217
+ ## Beyond testing
218
+
219
+ The libraries were built to test SAP, and that stays their core. What makes a
220
+ test trustworthy (write a record through one channel, read it back through
221
+ another, independent one, delete it, and confirm it is gone) also works outside
222
+ a test. Three uses follow from it:
223
+
224
+ - **Test data sets**: creating complete, consistent data sets, identifiable as
225
+ test data, to feed test campaigns.
226
+ - **Populating databases for performance testing**: filling empty or incomplete
227
+ SAP databases before a load campaign.
228
+ - **Configuration and migration loads**: loading complex business data into a
229
+ target environment, and cross-checking the load through a second channel, for
230
+ instance in an ECC to S/4HANA migration.
231
+
232
+ To be precise about where this stands: writing, deleting and cross-checking
233
+ through two channels are validated live on SAP development systems, never on a
234
+ customer system. The three uses themselves are a direction, not delivered
235
+ features. There is no data-set generator in the libraries yet, no volume or load
236
+ time has been measured, and no migration has been run. The angle for migrations
237
+ is scripted loading plus cross-checking, not replacing SAP's own load and
238
+ migration tools.
239
+
240
+ ## Documentation
241
+
242
+ | Document | Topic |
243
+ | --- | --- |
244
+ | [Keyword reference](https://cyrilm29.github.io/robotframework-sapfx/) | Every keyword of the three libraries |
245
+ | [docs/architecture.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/architecture.md) | How the libraries are built and how they fit together |
246
+ | [docs/fiori-architecture.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/fiori-architecture.md) | The web side: UI5 selectors, engines, frames, hybrid pages |
247
+ | [docs/testing-without-sap.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/testing-without-sap.md) | A free local SAP system, SAP-side prerequisites |
248
+ | [docs/sap-test-data.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/sap-test-data.md) | Test data and targets available without a customer system |
249
+ | [docs/ecc-validation.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/ecc-validation.md) | Validation against a live ABAP system, step by step |
250
+ | [docs/hardening-test-environment.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/hardening-test-environment.md) | Security checklist for the server, the workstation and the web side |
251
+ | [docs/migrating-from-sapguilibrary.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/migrating-from-sapguilibrary.md) | Moving from robotframework-sapguilibrary |
252
+ | [docs/migrating-from-cbta.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/migrating-from-cbta.md) | Moving from SAP CBTA |
253
+ | [docs/audit-upstream.md](https://github.com/CyrilM29/robotframework-sapfx/blob/main/docs/audit-upstream.md) | What SapEccLibrary changes in the upstream code it embeds, and why |
254
+
255
+ Every document exists in English and in French (`*.fr.md`). They were written
256
+ alongside the libraries in the maintainer's workbench: when they mention a
257
+ business resource layer (`resources/`), Robot suites (`tests/robot/`),
258
+ recorders or test agents, they describe that workbench, which is not part of
259
+ this repository.
260
+
261
+ ## Layout
262
+
263
+ ```text
264
+ src/SapEccLibrary/ SAP GUI for Windows (COM); keywords/ one mixin per
265
+ capability, robotframework-sapguilibrary's included
266
+ src/SapFioriLibrary/ Fiori / UI5 / Web Components / SAP GUI for HTML
267
+ (Browser library); injected JavaScript in *.js.tpl
268
+ src/SapApiLibrary/ OData v2/v4 and optional RFC / BAPI
269
+ src/sapfx_common/ shared pure logic
270
+ docs/ library documentation (EN/FR), docs/libdoc/ = keyword pages
271
+ ```
272
+
273
+ ## Issues
274
+
275
+ Bug reports and suggestions are welcome as
276
+ [GitHub issues](https://github.com/CyrilM29/robotframework-sapfx/issues).
277
+
278
+ ## License
279
+
280
+ Apache 2.0. Includes code absorbed from robotframework-sapguilibrary, locator
281
+ engines ported from playwright-sap and techniques adapted from RoboSAPiens and
282
+ playwright-praman; see [LICENSE](https://github.com/CyrilM29/robotframework-sapfx/blob/main/LICENSE) and [NOTICE](https://github.com/CyrilM29/robotframework-sapfx/blob/main/NOTICE).
283
+
284
+ ## Trademarks
285
+
286
+ SAP, SAP ECC, SAP S/4HANA, SAP Fiori, SAP BTP, SAP HANA, SAP NetWeaver, SAP
287
+ GUI, SAPUI5, ABAP and the other SAP products and services mentioned are
288
+ trademarks or registered trademarks of SAP SE or its affiliates in Germany and
289
+ in other countries. SAPFX is an independent open-source project, not affiliated
290
+ with, sponsored or endorsed by SAP SE.