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.
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/NOTICE +8 -3
- robotframework_sapfx-0.8.4/PKG-INFO +334 -0
- robotframework_sapfx-0.8.4/README.md +290 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/pyproject.toml +5 -60
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/SapApiLibrary.py +87 -37
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/__init__.py +1 -1
- robotframework_sapfx-0.8.4/src/SapApiLibrary/_bapi.py +158 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_discovery.py +128 -20
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_http_security.py +22 -8
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_odata_read.py +71 -14
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_odata_write.py +57 -20
- robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc.py +325 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_rfc_extract.py +26 -11
- robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_idoc.py +360 -0
- robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_idoc_profiles.py +211 -0
- robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_idoc_wait.py +188 -0
- robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_jobs.py +318 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_rfc_reads.py +93 -35
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_rfc_security.py +71 -18
- robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_spool.py +335 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_rfc_surface.py +52 -20
- robotframework_sapfx-0.8.4/src/SapApiLibrary/_rfc_surface_artifact.py +115 -0
- robotframework_sapfx-0.8.4/src/SapApiLibrary/_xbp.py +158 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/SapEccLibrary.py +105 -114
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/__init__.py +2 -2
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/__init__.py +39 -9
- robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_abap_list.py +106 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_combobox.py +110 -18
- robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_connection.py +447 -0
- robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_connection_probe.py +130 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_ddic.py +81 -7
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_diagnostics.py +61 -21
- robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_elements.py +282 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_embedded_browser.py +19 -11
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_grid.py +132 -74
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_grid_actions.py +101 -22
- robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_grid_cells.py +172 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_healing.py +18 -8
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_identity.py +20 -4
- robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_inputs.py +252 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_menus.py +19 -4
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_perception.py +101 -78
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_pointer.py +18 -11
- robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_screenshots.py +365 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_se16.py +68 -16
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_semantic.py +137 -37
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_sessions.py +62 -21
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_statusbar.py +15 -3
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_table_control.py +59 -19
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_tabstrip.py +26 -5
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_toolbar.py +13 -3
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_trees.py +177 -18
- robotframework_sapfx-0.8.4/src/SapEccLibrary/keywords/_value_checks.py +80 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_visual.py +39 -20
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_waits.py +152 -15
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_watch.py +18 -13
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/keywords/_windows.py +119 -12
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/SapFioriLibrary.py +7 -4
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/__init__.py +1 -1
- robotframework_sapfx-0.8.4/src/SapFioriLibrary/_flp_js.py +156 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_capture.js.tpl +56 -12
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_core.js.tpl +5 -0
- robotframework_sapfx-0.8.4/src/SapFioriLibrary/_ui5_bundle_dates.js.tpl +164 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_engines.js.tpl +1 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_js.py +12 -6
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_runtime.py +25 -7
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_spy_core.js.tpl +4 -1
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_spy_exports.js.tpl +31 -7
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_spy_record.js.tpl +29 -3
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_spy_replay.js.tpl +6 -1
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_webgui_js.py +1 -1
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/__init__.py +4 -1
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_actions.py +134 -18
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_base.py +11 -7
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_composition.py +18 -9
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_engines.py +143 -48
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_flp.py +56 -32
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_flp_services.py +60 -24
- robotframework_sapfx-0.8.4/src/SapFioriLibrary/keywords/_flp_tile_refresh.py +191 -0
- robotframework_sapfx-0.8.4/src/SapFioriLibrary/keywords/_flp_tiles.py +340 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_frames.py +60 -29
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_locators.py +120 -61
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_perception.py +83 -42
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_state.py +73 -37
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/keywords/_tables.py +18 -4
- robotframework_sapfx-0.8.4/src/robotframework_sapfx.egg-info/PKG-INFO +334 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/robotframework_sapfx.egg-info/SOURCES.txt +29 -2
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/__init__.py +1 -1
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/_semantic_match.py +47 -1
- robotframework_sapfx-0.8.4/src/sapfx_common/abap_components.py +71 -0
- robotframework_sapfx-0.8.4/src/sapfx_common/abap_list.py +256 -0
- robotframework_sapfx-0.8.4/src/sapfx_common/background_jobs.py +261 -0
- robotframework_sapfx-0.8.4/src/sapfx_common/bapi_return.py +146 -0
- robotframework_sapfx-0.8.4/src/sapfx_common/cds_source.py +232 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/com_safety.py +71 -2
- robotframework_sapfx-0.8.4/src/sapfx_common/flp_tiles.py +345 -0
- robotframework_sapfx-0.8.4/src/sapfx_common/idoc.py +377 -0
- robotframework_sapfx-0.8.4/src/sapfx_common/idoc_profiles.py +198 -0
- robotframework_sapfx-0.8.4/src/sapfx_common/idoc_status.py +199 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/odata_metadata.py +20 -2
- robotframework_sapfx-0.8.4/src/sapfx_common/rap_preview.py +161 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/rfc_channel.py +4 -2
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/rfc_extract.py +47 -13
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/rfc_reads.py +62 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/rfc_tables.py +42 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/semantic.py +36 -15
- robotframework_sapfx-0.8.4/src/sapfx_common/spool.py +312 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_control.py +28 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/tree_nodes.py +18 -0
- robotframework_sapfx-0.8.4/src/sapfx_common/ui5_dates.py +117 -0
- robotframework_sapfx-0.8.4/src/sapfx_common/vkeys.py +83 -0
- robotframework_sapfx-0.8.2/PKG-INFO +0 -400
- robotframework_sapfx-0.8.2/README.md +0 -355
- robotframework_sapfx-0.8.2/src/SapApiLibrary/_rfc.py +0 -482
- robotframework_sapfx-0.8.2/src/SapEccLibrary/_vendor/__init__.py +0 -4
- robotframework_sapfx-0.8.2/src/SapEccLibrary/_vendor/sapgui_base.py +0 -791
- robotframework_sapfx-0.8.2/src/SapEccLibrary/keywords/_connection.py +0 -253
- robotframework_sapfx-0.8.2/src/SapEccLibrary/keywords/_screenshots.py +0 -206
- robotframework_sapfx-0.8.2/src/robotframework_sapfx.egg-info/PKG-INFO +0 -400
- robotframework_sapfx-0.8.2/src/sapfx_common/abap_list.py +0 -48
- robotframework_sapfx-0.8.2/src/sapfx_common/bapi_return.py +0 -64
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/LICENSE +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/setup.cfg +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_core.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/_http.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapApiLibrary/py.typed +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapEccLibrary/py.typed +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_info.js.tpl +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_shadow.js.tpl +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_ui5_bundle_tables.js.tpl +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_webgui_grid.js.tpl +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/_webgui_selection.js.tpl +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/py.typed +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/SapFioriLibrary/regen_recorder.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/robotframework_sapfx.egg-info/dependency_links.txt +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/robotframework_sapfx.egg-info/requires.txt +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/robotframework_sapfx.egg-info/top_level.txt +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/_cross_channel_artifact.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/_cross_channel_contract.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/_tabular.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/_tabular_io.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/alv_cells.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/artifacts.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/auth_flows.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/client_security.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/combo_box.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/cross_channel.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/ddic_inventory.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/fiori_diagnostics.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/gateway_status.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/healing.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/healing_telemetry.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/http_security.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/menu_path.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/object_tree.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/odata_batch.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/parameter_origin.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/perception_diff.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/polling.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/py.typed +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/rfc_surface.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/robot_args.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/screen_watch.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/secrets.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/security_baseline.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/security_inventory.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/security_surface.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/session_context.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/status_message.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/system_identity.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/tab_strip.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_csv.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_extract.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_json.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_parquet.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_svg.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/table_xlsx.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/user_formats.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/visual_baseline.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/visual_hash.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/vocabulary.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/web_cookies.py +0 -0
- {robotframework_sapfx-0.8.2 → robotframework_sapfx-0.8.4}/src/sapfx_common/webgui_selection.py +0 -0
- {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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
+
[](https://pypi.org/project/robotframework-sapfx/)
|
|
52
|
+
[](https://pypi.org/project/robotframework-sapfx/)
|
|
53
|
+
[](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
|
+
[](https://pypi.org/project/robotframework-sapfx/)
|
|
8
|
+
[](https://pypi.org/project/robotframework-sapfx/)
|
|
9
|
+
[](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.
|