update repository structure and unit tests (#436)

* fix error message

* popup close fix

* refactoring

* refactoring

* refactoring

* Create abaplint-fix

* update

* update

* refactoring

* refactoring

* update

* update

* update abaplint

* refactoring

* update

* unit tests utility class

* update unit tests

* update unit tests

* update

* update

* update unit tests

* update

* Update z2ui5_cl_xml_view.clas.locals_imp.abap

* Delete z2ui5_cl_xml_view.clas.locals_imp.abap

* Update package.devc.xml

* update start page

* update unit tests and organization

* update abaplint

* update abaplint

* update abaplint fixes

* update

* update

* update abalint issues

* Delete z2ui5_cl_http_handler.clas.locals_imp.abap

* update downport readiness

* update downport readiness

* Update README.md

* update abaplint

* update

* abaplint fixes

* update unit tests

* update unit tests

* update abaplint

* update

* update unit tests sequence

* update sequence

* update unit test order

* Update abaplint.jsonc

* exclude unit test

* update unit test syntax

* added unit test nested xsdbool

* update unit tests

* upadate

* unit tests

* unit tests

* update unit tests

* update

* update version
This commit is contained in:
oblomov 2023-07-30 17:21:17 +02:00 committed by GitHub
parent 7714f4e53c
commit 1b09a2bb6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 4500 additions and 3701 deletions

View File

@ -44,8 +44,8 @@
* Want to help out? see the contribution guidelines [(abap2UI5/contribution)](https://github.com/abap2UI5/abap2UI5/blob/main/CONTRIBUTING.md)
#### Apps & Extensions
* Integrate your apps in launchpads and other services [(abap2UI5/ext-service_integration)](https://github.com/abap2UI5/ext-service_integration)
* Try out abap2UI5-tools, a useful collection of tools & apps [(abap2UI5/tools)](https://github.com/abap2UI5/app-tools)
* Integrate your apps in launchpads and other services [(ext-service_integration)](https://github.com/abap2UI5/ext-service_integration)
* Try out abap2UI5-tools, a useful collection of tools & apps [(ext-app_tools)](https://github.com/abap2UI5/app-tools)
* Check out other projects using abap2UI5 [(abap2UI5/links)](https://github.com/abap2UI5/abap2UI5-documentation/blob/main/docs/links.md)
* And finally: Don't forget to explore the [Samples Repository 🧭](https://github.com/abap2UI5/abap2UI5-samples)

258
abaplint-max_fix.jsonc Normal file
View File

@ -0,0 +1,258 @@
{
"global": {
"files": "/src/**/*.*"
},
"dependencies": [
{
"url": "https://github.com/abapedia/steampunk-2305-api",
"folder": "/deps",
"files": "/src/**/*.*"
}
],
"syntax": {
"version": "v750",
"errorNamespace": "."
},
"rules": {
"7bit_ascii": true,
"abapdoc": true,
"sql_value_conversion" : true,
"select_single_full_key" : true,
"strict_sql" : true,
"easy_to_find_messages" : true,
"fully_type_itabs" : true,
"align_parameters": true,
"smim_consistency": true,
"allowed_object_naming": true,
"allowed_object_types": true,
"ambiguous_statement": true,
"avoid_use": true,
"begin_end_names": true,
"begin_single_include": true,
"call_transaction_authority_check": true,
"cds_comment_style": true,
"cds_legacy_view": true,
"cds_parser_error": true,
"chain_mainly_declarations": true,
"change_if_to_case": {
"exclude": [],
"severity": "Error",
"skipNames": []
},
"check_abstract": true,
"check_comments": true,
"check_ddic": true,
"check_include": true,
"check_subrc": true,
"check_syntax": true,
"check_text_elements": true,
"check_transformation_exists": true,
"class_attribute_names": true,
"classic_exceptions_overlap": true,
"cloud_types": true,
"colon_missing_space": true,
"commented_code": true,
"constant_classes": {
"exclude": [],
"severity": "Error",
"mapping": []
},
"constructor_visibility_public": true,
"contains_tab": {
"exclude": [],
"severity": "Error",
"spaces": 1
},
"cyclic_oo": true,
"cyclomatic_complexity": {
"exclude": [],
"severity": "Error",
"max": 20
},
"dangerous_statement": true,
"db_operation_in_loop": true,
"definitions_top": true,
"description_empty": true,
"double_space": true,
"downport": true,
"empty_line_in_statement": true,
"empty_statement": true,
"empty_structure": {
"loop": true,
"if": true,
"while": true,
"case": true,
"select": true,
"do": true,
"at": true,
"try": true,
"when": true
},
"exit_or_check": true,
"expand_macros": true,
"exporting": true,
"forbidden_identifier": true,
"forbidden_pseudo_and_pragma": {
"exclude": [],
"severity": "Error",
"pseudo": [],
"pragmas": [],
"ignoreGlobalClassDefinition": true,
"ignoreGlobalInterface": true
},
"forbidden_void_type": true,
"form_tables_obsolete": true,
"fully_type_constants": {
"checkData": true
},
"function_module_recommendations": true,
"functional_writing": {
"ignoreExceptions": true
},
"global_class": true,
"identical_conditions": true,
"identical_contents": true,
"identical_descriptions": true,
"identical_form_names": true,
"if_in_if": true,
"implement_methods": true,
"in_statement_indentation": true,
"indentation": true,
"inline_data_old_versions": true,
"intf_referencing_clas": true,
"keep_single_parameter_on_one_line": true,
"keyword_case": true,
"line_break_multiple_parameters": true,
"line_break_style": true,
"line_length": true,
"line_only_punc": true,
"local_class_naming": true,
"local_testclass_consistency": true,
"local_variable_names": true,
"main_file_contents": true,
"many_parentheses": true,
"max_one_method_parameter_per_line": true,
"max_one_statement": true,
"message_exists": true,
"method_implemented_twice": true,
"method_length": true,
"method_overwrites_builtin": true,
"method_parameter_names": true,
"mix_returning": true,
"modify_only_own_db_tables": {
"reportDynamic": true,
"ownTables": "^[yz]"
},
"msag_consistency": true,
"names_no_dash": true,
"nesting": {
"depth": 5
},
"newline_between_methods": true,
"no_aliases": true,
"no_chained_assignment": true,
"no_external_form_calls": true,
"no_inline_in_optional_branches": true,
"no_public_attributes": true,
"no_yoda_conditions": true,
"nrob_consistency": true,
"object_naming": {
"exclude": [],
"severity": "Error",
"patternKind": "required",
"ignoreNames": [],
"ignorePatterns": [],
"clas": "^Z2UI5_C(L|X)",
"intf": "^Z2UI5_IF",
"prog": "^Z",
"fugr": "^Z",
"tabl": "^Z",
"ttyp": "^Z",
"dtel": "^Z",
"doma": "^Z",
"msag": "^Z",
"tran": "^Z",
"enqu": "^EZ",
"auth": "^Z",
"pinf": "^Z",
"idoc": "^Z",
"xslt": "^Z",
"ssfo": "^Z",
"ssst": "^Z",
"shlp": "^Z"
},
"obsolete_statement": true,
"omit_parameter_name": true,
"omit_preceding_zeros": true,
"omit_receiving": true,
"parser_702_chaining": true,
"parser_error": true,
"parser_missing_space": true,
"pragma_style": true,
"prefer_corresponding": true,
"prefer_inline": {
"severity": "Warning"
},
"prefer_is_not": true,
"prefer_raise_exception_new": true,
"prefer_returning_to_exporting": true,
"prefer_xsdbool": true,
"preferred_compare_operator": true,
"prefix_is_current_class": {
"severity": "Warning"
},
"reduce_string_templates": true,
"release_idoc": true,
"remove_descriptions": {
"exclude": [],
"severity": "Error",
"ignoreExceptions": true,
"ignoreWorkflow": true
},
"rfc_error_handling": true,
"select_add_order_by": true,
"select_performance": true,
"selection_screen_naming": true,
"sequential_blank": {
"severity": "Warning"
},
"short_case": true,
"sicf_consistency": true,
"slow_parameter_passing": true,
"space_before_colon": true,
"space_before_dot": true,
"sql_escape_host_variables": true,
"start_at_tab": true,
"static_call_via_instance": {
"allowInTestclassIncludes": true
},
"superclass_final": true,
"superfluous_value": true,
"sy_modification": true,
"tabl_enhancement_category": true,
"try_without_catch": true,
"type_form_parameters": true,
"types_naming": true,
"uncaught_exception": true,
"unknown_types": true,
"unnecessary_chaining": true,
"unnecessary_pragma": true,
"unnecessary_return": true,
"unreachable_code": true,
"unsecure_fae": true,
"unused_ddic": true,
"unused_methods": true,
"unused_types": true,
"unused_variables": {
"severity": "Error",
"skipNames": ["lv_dummy", "i_mv_editor"]
},
"use_bool_expression": true,
"use_class_based_exceptions": true,
"use_line_exists": true,
"use_new": true,
"when_others_last": true,
"whitespace_end": true,
"xml_consistency": true
}
}

View File

@ -241,13 +241,16 @@
"unnecessary_chaining": true,
"unnecessary_pragma": true,
"unnecessary_return": true,
"unreachable_code": true,
"unreachable_code": {
"exclude": ["z2ui5_cl_fw_utility.clas.testclasses.abap"]
},
"unsecure_fae": true,
"unused_ddic": true,
"unused_methods": true,
"unused_types": true,
"unused_variables": {
"severity": "Error",
"exclude": ["z2ui5_cl_fw_utility.clas.testclasses.abap"],
"skipNames": ["lv_dummy", "i_mv_editor"]
},
"use_bool_expression": true,

56
package-lock.json generated
View File

@ -9,16 +9,16 @@
"version": "1.0.0",
"license": "MIT",
"devDependencies": {
"@abaplint/cli": "^2.101.6",
"@abaplint/database-sqlite": "^2.7.13",
"@abaplint/runtime": "^2.7.14",
"@abaplint/transpiler-cli": "^2.7.14"
"@abaplint/cli": "^2.102.11",
"@abaplint/database-sqlite": "^2.7.18",
"@abaplint/runtime": "^2.7.55",
"@abaplint/transpiler-cli": "^2.7.55"
}
},
"node_modules/@abaplint/cli": {
"version": "2.101.6",
"resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.101.6.tgz",
"integrity": "sha512-RFH0Rs3Pe4+8O7Je7Xrye0C+BPhH654WMtdNk+5O5tiJQesKrSPK9rKr8GhTCHpY2V3paYFCHkP8b9DymdxPrw==",
"version": "2.102.11",
"resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.102.11.tgz",
"integrity": "sha512-APdQdrRjN4dUSKkEB1ABm9qijcCa1HWpNFLFGgZgTFVUl2T4PSnTkouJtc6Rad/1A/fB6I0c2lWnOxQV9c3dZA==",
"dev": true,
"bin": {
"abaplint": "abaplint"
@ -31,18 +31,18 @@
}
},
"node_modules/@abaplint/database-sqlite": {
"version": "2.7.13",
"resolved": "https://registry.npmjs.org/@abaplint/database-sqlite/-/database-sqlite-2.7.13.tgz",
"integrity": "sha512-zansX431Tm2u+S84hIG7QrGUlfWGamikLYzp+erniiRbft1BoxWD7WeGaNR7J26MIzlnVpYRHPJUvWi0Z+dLRA==",
"version": "2.7.18",
"resolved": "https://registry.npmjs.org/@abaplint/database-sqlite/-/database-sqlite-2.7.18.tgz",
"integrity": "sha512-NY1D+39sh9WQV2pmDR0mFM4C0bNI9CTTlbSUhXrUcq8X26rfLjYemGHJ/J/G90W/W9xx6Do4lMzgGep7sMqZ1w==",
"dev": true,
"dependencies": {
"sql.js": "^1.8.0"
}
},
"node_modules/@abaplint/runtime": {
"version": "2.7.14",
"resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.7.14.tgz",
"integrity": "sha512-ZUN6c4xkKgSoi0RALF8/HvgyYiOiF7ISEQyehz/8jhAq7qbxR9kzcrQzidVnNLlsMTqwVFH3XxsiL2ZWtV0CoQ==",
"version": "2.7.55",
"resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.7.55.tgz",
"integrity": "sha512-bNQ4nexrF2oLQ3d8baj8rSn6s1V19RqimF4sPwBawnUH9jAXb99zxysYFEqMf/R6aTmPUjnPgB9PLnYPPJ6FoA==",
"dev": true,
"dependencies": {
"temporal-polyfill": "^0.1.1"
@ -52,9 +52,9 @@
}
},
"node_modules/@abaplint/transpiler-cli": {
"version": "2.7.14",
"resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.7.14.tgz",
"integrity": "sha512-oAXu0K95RfELbqPcF1YJZWMk/ZdmHlkG8osfRfqqdN0LOxvvdZuMC/eVw16el7P6u5TDlqBL+sJq6sxkvxL72w==",
"version": "2.7.55",
"resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.7.55.tgz",
"integrity": "sha512-tgSib6t6TnHsQfmm0a6wLoF0vdpw9nyq24laZMXGNWXADN4442kj5/6NUYo8CJ/0gxqK94P3lQwem0ZkQIZSVA==",
"dev": true,
"bin": {
"abap_transpile": "abap_transpile"
@ -87,33 +87,33 @@
},
"dependencies": {
"@abaplint/cli": {
"version": "2.101.6",
"resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.101.6.tgz",
"integrity": "sha512-RFH0Rs3Pe4+8O7Je7Xrye0C+BPhH654WMtdNk+5O5tiJQesKrSPK9rKr8GhTCHpY2V3paYFCHkP8b9DymdxPrw==",
"version": "2.102.11",
"resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.102.11.tgz",
"integrity": "sha512-APdQdrRjN4dUSKkEB1ABm9qijcCa1HWpNFLFGgZgTFVUl2T4PSnTkouJtc6Rad/1A/fB6I0c2lWnOxQV9c3dZA==",
"dev": true
},
"@abaplint/database-sqlite": {
"version": "2.7.13",
"resolved": "https://registry.npmjs.org/@abaplint/database-sqlite/-/database-sqlite-2.7.13.tgz",
"integrity": "sha512-zansX431Tm2u+S84hIG7QrGUlfWGamikLYzp+erniiRbft1BoxWD7WeGaNR7J26MIzlnVpYRHPJUvWi0Z+dLRA==",
"version": "2.7.18",
"resolved": "https://registry.npmjs.org/@abaplint/database-sqlite/-/database-sqlite-2.7.18.tgz",
"integrity": "sha512-NY1D+39sh9WQV2pmDR0mFM4C0bNI9CTTlbSUhXrUcq8X26rfLjYemGHJ/J/G90W/W9xx6Do4lMzgGep7sMqZ1w==",
"dev": true,
"requires": {
"sql.js": "^1.8.0"
}
},
"@abaplint/runtime": {
"version": "2.7.14",
"resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.7.14.tgz",
"integrity": "sha512-ZUN6c4xkKgSoi0RALF8/HvgyYiOiF7ISEQyehz/8jhAq7qbxR9kzcrQzidVnNLlsMTqwVFH3XxsiL2ZWtV0CoQ==",
"version": "2.7.55",
"resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.7.55.tgz",
"integrity": "sha512-bNQ4nexrF2oLQ3d8baj8rSn6s1V19RqimF4sPwBawnUH9jAXb99zxysYFEqMf/R6aTmPUjnPgB9PLnYPPJ6FoA==",
"dev": true,
"requires": {
"temporal-polyfill": "^0.1.1"
}
},
"@abaplint/transpiler-cli": {
"version": "2.7.14",
"resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.7.14.tgz",
"integrity": "sha512-oAXu0K95RfELbqPcF1YJZWMk/ZdmHlkG8osfRfqqdN0LOxvvdZuMC/eVw16el7P6u5TDlqBL+sJq6sxkvxL72w==",
"version": "2.7.55",
"resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.7.55.tgz",
"integrity": "sha512-tgSib6t6TnHsQfmm0a6wLoF0vdpw9nyq24laZMXGNWXADN4442kj5/6NUYo8CJ/0gxqK94P3lQwem0ZkQIZSVA==",
"dev": true
},
"sql.js": {

View File

@ -19,9 +19,9 @@
},
"homepage": "https://github.com/abap2UI5/abap2UI5#readme",
"devDependencies": {
"@abaplint/cli": "^2.101.6",
"@abaplint/database-sqlite": "^2.7.13",
"@abaplint/runtime": "^2.7.14",
"@abaplint/transpiler-cli": "^2.7.14"
"@abaplint/cli": "^2.102.11",
"@abaplint/database-sqlite": "^2.7.18",
"@abaplint/runtime": "^2.7.55",
"@abaplint/transpiler-cli": "^2.7.55"
}
}

11
src/00/package.devc.xml Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DEVC" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DEVC>
<CTEXT>abap2UI5 internal</CTEXT>
<TPCLASS>X</TPCLASS>
</DEVC>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,251 @@
CLASS z2ui5_cl_fw_app DEFINITION
PUBLIC
FINAL
CREATE PROTECTED.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
DATA:
BEGIN OF ms_home,
btn_text TYPE string,
btn_event_id TYPE string,
btn_icon TYPE string,
classname TYPE string,
class_value_state TYPE string,
class_value_state_text TYPE string,
class_editable TYPE abap_bool VALUE abap_true,
END OF ms_home.
CLASS-METHODS factory_start
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_app.
CLASS-METHODS factory_error
IMPORTING
error TYPE REF TO cx_root
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_app.
DATA client TYPE REF TO z2ui5_if_client.
DATA mv_check_initialized TYPE abap_bool.
DATA mv_check_demo TYPE abap_bool.
DATA mx_error TYPE REF TO cx_root.
METHODS z2ui5_on_init.
METHODS z2ui5_on_event.
METHODS view_display_error.
METHODS view_display_start.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS Z2UI5_CL_FW_APP IMPLEMENTATION.
METHOD factory_error.
result = NEW #( ).
result->mx_error = error.
ENDMETHOD.
METHOD factory_start.
result = NEW #( ).
ENDMETHOD.
METHOD view_display_error.
DATA(lv_url) = shift_left( val = client->get( )-s_config-origin && client->get( )-s_config-pathname
sub = ` ` ).
DATA(lv_url_app) = lv_url && client->get( )-s_config-search.
DATA(view) = z2ui5_cl_xml_view=>factory( client )->shell( )->illustrated_message(
enableformattedtext = abap_true
illustrationtype = 'sapIllus-ErrorScreen'
title = '500 Internal Server Error'
description = mx_error->get_text( )
)->additional_content(
)->button(
text = 'Home'
type = 'Emphasized'
press = client->_event_client( action = client->cs_event-location_reload t_arg = VALUE #( ( lv_url ) ) )
)->button(
text = 'Restart'
press = client->_event_client( action = client->cs_event-location_reload t_arg = VALUE #( ( lv_url_app ) ) ) ).
client->view_display( view->stringify( ) ).
ENDMETHOD.
METHOD view_display_start.
DATA(lv_url) = z2ui5_cl_xml_view=>factory( client )->hlp_get_app_url( ms_home-classname ).
DATA(page) = z2ui5_cl_xml_view=>factory( client )->shell(
)->page( shownavbutton = abap_false ).
page->header_content(
)->title( `abap2UI5 - Developing UI5 Apps in pure ABAP`
)->toolbar_spacer(
)->link( text = `SCN`
target = `_blank`
href = `https://blogs.sap.com/tag/abap2ui5/`
)->link( text = `Twitter`
target = `_blank`
href = `https://twitter.com/abap2UI5`
)->link( text = `GitHub`
target = `_blank`
href = `https://github.com/abap2ui5/abap2ui5` ).
DATA(grid) = page->grid( `XL7 L7 M12 S12`
)->content( `layout` ).
DATA(content) = grid->simple_form( title = `Quickstart`
layout = `ResponsiveGridLayout`
editable = `true`
)->content( `form` ).
content->label( `Step 1`
)->text( `Create a global class in your abap system`
)->label( `Step 2`
)->text( `Add the interface: Z2UI5_IF_APP`
)->label( `Step 3`
)->text( `Define view, implement behaviour`
)->link( text = `(Example)`
target = `_blank`
href = `https://github.com/abap2ui5/ABAP2UI5/blob/main/src/z2ui5_cl_app_hello_world.clas.abap`
)->label( `Step 4` ).
IF ms_home-class_editable = abap_true.
content->input( placeholder = `fill in the class name and press 'check'`
editable = z2ui5_cl_fw_utility=>get_json_boolean( ms_home-class_editable )
value = client->_bind_edit( ms_home-classname ) ).
ELSE.
content->text( ms_home-classname ).
ENDIF.
content->button( press = client->_event( ms_home-btn_event_id )
text = ms_home-btn_text
icon = ms_home-btn_icon
)->label( `Step 5`
)->link( text = `Link to the Application`
target = `_blank`
href = lv_url
enabled = z2ui5_cl_fw_utility=>get_json_boolean( xsdbool( ms_home-class_editable = abap_false ) ) ).
DATA(form) = grid->simple_form( title = `Samples`
editable = abap_true
layout = 'ResponsiveGridLayout' ).
IF mv_check_demo = abap_false.
form->message_strip( text = 'Oops! You need to install abap2UI5 demos before continuing...'
type = 'Warning'
)->get( )->_generic( 'link' )->link( text = `(HERE)`
target = '_blank'
href = `https://github.com/oblomov-dev/abap2UI5-demos` ).
ENDIF.
form->content( `form` )->label( )->button(
text = 'Continue...'
press = client->_event( val = `DEMOS` check_view_destroy = abap_true )
enabled = xsdbool( mv_check_demo = abap_true )
)->button( visible = abap_false )->link( text = 'More on GitHub...'
target = '_blank'
href = 'https://github.com/abap2UI5/abap2UI5-documentation/blob/main/docs/links.md' ).
client->view_display( form->stringify( ) ).
ENDMETHOD.
METHOD z2ui5_if_app~main.
me->client = client.
IF mv_check_initialized = abap_false.
mv_check_initialized = abap_true.
z2ui5_on_init( ).
ENDIF.
z2ui5_on_event( ).
IF mx_error IS BOUND.
view_display_error( ).
ELSE.
view_display_start( ).
ENDIF.
ENDMETHOD.
METHOD z2ui5_on_event.
CASE client->get( )-event.
WHEN `BUTTON_CHANGE`.
ms_home-btn_text = `check`.
ms_home-btn_event_id = `BUTTON_CHECK`.
ms_home-btn_icon = `sap-icon://validate`.
ms_home-class_editable = abap_true.
WHEN `BUTTON_CHECK`.
TRY.
DATA li_app_test TYPE REF TO z2ui5_if_app.
ms_home-classname = z2ui5_cl_fw_utility=>get_trim_upper( ms_home-classname ).
CREATE OBJECT li_app_test TYPE (ms_home-classname).
client->message_toast_display( `App is ready to start!` ).
ms_home-btn_text = `edit`.
ms_home-btn_event_id = `BUTTON_CHANGE`.
ms_home-btn_icon = `sap-icon://edit`.
ms_home-class_value_state = `Success`.
ms_home-class_editable = abap_false.
CATCH cx_root INTO DATA(lx) ##CATCH_ALL.
ms_home-class_value_state_text = lx->get_text( ).
ms_home-class_value_state = `Warning`.
client->message_box_display( text = ms_home-class_value_state_text
type = `error` ).
ENDTRY.
WHEN `DEMOS`.
DATA li_app TYPE REF TO z2ui5_if_app.
TRY.
CREATE OBJECT li_app TYPE (`Z2UI5_CL_APP_DEMO_00`).
mv_check_demo = abap_true.
client->nav_app_call( li_app ).
CATCH cx_root.
mv_check_demo = abap_false.
ENDTRY.
ENDCASE.
ENDMETHOD.
METHOD z2ui5_on_init.
IF mx_error IS NOT BOUND.
ms_home-btn_text = `check`.
ms_home-btn_event_id = `BUTTON_CHECK`.
ms_home-class_editable = abap_true.
ms_home-btn_icon = `sap-icon://validate`.
ms_home-classname = `z2ui5_cl_app_hello_world`.
ENDIF.
mv_check_demo = abap_true.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>Z2UI5_CL_FW_APP</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abap2UI5 - framework app</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,254 @@
CLASS z2ui5_cl_fw_client DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES z2ui5_if_client.
DATA mo_handler TYPE REF TO z2ui5_cl_fw_handler.
METHODS constructor
IMPORTING
handler TYPE REF TO z2ui5_cl_fw_handler.
ENDCLASS.
CLASS Z2UI5_CL_FW_CLIENT IMPLEMENTATION.
METHOD constructor.
mo_handler = handler.
ENDMETHOD.
METHOD z2ui5_if_client~cursor_set.
mo_handler->ms_next-s_set-s_cursor = VALUE #(
id = id
cursorpos = cursorpos
selectionend = selectionend
selectionstart = selectionstart ).
ENDMETHOD.
METHOD z2ui5_if_client~get.
result = VALUE #(
event = mo_handler->ms_actual-event
check_launchpad_active = mo_handler->ms_actual-check_launchpad_active
t_event_arg = mo_handler->ms_actual-t_event_arg
t_scroll_pos = mo_handler->ms_actual-t_scroll_pos
s_draft = CORRESPONDING #( mo_handler->ms_db )
check_on_navigated = mo_handler->ms_actual-check_on_navigated
s_config = z2ui5_cl_fw_handler=>ss_config ).
ENDMETHOD.
METHOD z2ui5_if_client~get_app.
result = CAST #( z2ui5_cl_fw_db=>load_app( id )-app ).
ENDMETHOD.
METHOD z2ui5_if_client~message_box_display.
mo_handler->ms_next-s_set-s_msg_box = VALUE #( text = text type = type ).
ENDMETHOD.
METHOD z2ui5_if_client~message_toast_display.
mo_handler->ms_next-s_set-s_msg_toast = VALUE #( text = text ).
ENDMETHOD.
METHOD z2ui5_if_client~nav_app_call.
mo_handler->ms_next-o_app_call = app.
ENDMETHOD.
METHOD z2ui5_if_client~nav_app_leave.
mo_handler->ms_next-o_app_leave = app.
ENDMETHOD.
METHOD z2ui5_if_client~nest_view_destroy.
mo_handler->ms_next-s_set-s_view_nest-check_update_model = abap_true.
ENDMETHOD.
METHOD z2ui5_if_client~nest_view_display.
mo_handler->ms_next-s_set-s_view_nest-xml = val.
mo_handler->ms_next-s_set-s_view_nest-id = id.
mo_handler->ms_next-s_set-s_view_nest-method_destroy = method_destroy.
mo_handler->ms_next-s_set-s_view_nest-method_insert = method_insert.
ENDMETHOD.
METHOD z2ui5_if_client~nest_view_model_update.
mo_handler->ms_next-s_set-s_view_nest-check_update_model = abap_true.
ENDMETHOD.
METHOD z2ui5_if_client~popover_destroy.
mo_handler->ms_next-s_set-s_popover-check_destroy = abap_true.
ENDMETHOD.
METHOD z2ui5_if_client~popover_display.
mo_handler->ms_next-s_set-s_popover-check_destroy = abap_false.
mo_handler->ms_next-s_set-s_popover-xml = xml.
mo_handler->ms_next-s_set-s_popover-open_by_id = by_id.
ENDMETHOD.
METHOD z2ui5_if_client~popover_model_update.
mo_handler->ms_next-s_set-s_popover-check_update_model = abap_true.
ENDMETHOD.
METHOD z2ui5_if_client~popup_destroy.
mo_handler->ms_next-s_set-s_popup-check_destroy = abap_true.
ENDMETHOD.
METHOD z2ui5_if_client~popup_display.
mo_handler->ms_next-s_set-s_popup-check_destroy = abap_false.
mo_handler->ms_next-s_set-s_popup-xml = val.
ENDMETHOD.
METHOD z2ui5_if_client~popup_model_update.
mo_handler->ms_next-s_set-s_popup-check_update_model = abap_true.
ENDMETHOD.
METHOD z2ui5_if_client~scroll_position_set.
mo_handler->ms_next-s_set-t_scroll = val.
ENDMETHOD.
METHOD z2ui5_if_client~timer_set.
mo_handler->ms_next-s_set-s_timer-interval_ms = interval_ms.
mo_handler->ms_next-s_set-s_timer-event_finished = event_finished.
ENDMETHOD.
METHOD z2ui5_if_client~url_param_set.
mo_handler->ms_next-s_set-search = val.
mo_handler->ms_actual-s_config-search = val.
ENDMETHOD.
METHOD z2ui5_if_client~view_destroy.
mo_handler->ms_next-s_set-s_view-check_destroy = abap_true.
ENDMETHOD.
METHOD z2ui5_if_client~view_display.
mo_handler->ms_next-s_set-s_view-xml = val.
ENDMETHOD.
METHOD z2ui5_if_client~view_model_update.
mo_handler->ms_next-s_set-s_view-check_update_model = abap_true.
ENDMETHOD.
METHOD z2ui5_if_client~_bind.
result = mo_handler->_create_binding( value = val
type = z2ui5_cl_fw_handler=>cs_bind_type-one_way ).
IF path = abap_false.
result = `{` && result && `}`.
ENDIF.
ENDMETHOD.
METHOD z2ui5_if_client~_bind_edit.
result = mo_handler->_create_binding( value = val
type = z2ui5_cl_fw_handler=>cs_bind_type-two_way ).
IF path = abap_false.
result = `{` && result && `}`.
ENDIF.
ENDMETHOD.
METHOD z2ui5_if_client~_event.
result = `onEvent( { 'EVENT' : '` && val && `', 'METHOD' : 'UPDATE' , 'CHECK_VIEW_DESTROY' : ` && z2ui5_cl_fw_utility=>get_json_boolean( check_view_destroy ) && ` }`.
LOOP AT t_arg REFERENCE INTO DATA(lr_arg).
result = result && `, ` && lr_arg->*.
ENDLOOP.
result = result && ` )`.
ENDMETHOD.
METHOD z2ui5_if_client~_event_client.
result = `onEventFrontend( { 'EVENT' : '` && action && `'`.
IF t_arg IS NOT INITIAL.
result = result && `, 'T_ARG' : [`.
LOOP AT t_arg REFERENCE INTO DATA(lr_arg).
IF sy-tabix <> 1.
result = result && `,`.
ENDIF.
result = result && `'` && lr_arg->* && `'`.
ENDLOOP.
result = result && `]`.
ENDIF.
result = result && `})`.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,22 @@
CLASS ltcl_unit_test DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL critical.
PRIVATE SECTION.
METHODS first_test FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_test IMPLEMENTATION.
METHOD first_test.
DATA(lo_handler) = NEW z2ui5_cl_fw_handler( ).
DATA(lo_client) = NEW z2ui5_cl_fw_client( lo_handler ).
DATA(li_client) = CAST z2ui5_if_client( lo_client ) ##NEEDED.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>Z2UI5_CL_FW_CLIENT</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abap2UI5 - client</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,170 @@
CLASS z2ui5_cl_fw_db DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_s_db,
id TYPE string,
id_prev TYPE string,
id_prev_app TYPE string,
id_prev_app_stack TYPE string,
t_attri TYPE z2ui5_cl_fw_utility=>ty_t_attri,
app TYPE REF TO z2ui5_if_app,
END OF ty_s_db.
CLASS-METHODS create
IMPORTING
id TYPE string
db TYPE ty_s_db.
CLASS-METHODS load_app
IMPORTING
id TYPE clike
RETURNING
VALUE(result) TYPE ty_s_db.
CLASS-METHODS read
IMPORTING
id TYPE clike
check_load_app TYPE abap_bool DEFAULT abap_true
RETURNING
VALUE(result) TYPE z2ui5_t_draft.
CLASS-METHODS cleanup.
ENDCLASS.
CLASS Z2UI5_CL_FW_DB IMPLEMENTATION.
METHOD cleanup.
DATA(lv_time) = z2ui5_cl_fw_utility=>get_timestampl( ).
DATA(lv_four_hours_ago) = cl_abap_tstmp=>subtractsecs( tstmp = lv_time
secs = 60 * 60 * 4 ).
DELETE FROM z2ui5_t_draft WHERE timestampl < @lv_four_hours_ago.
COMMIT WORK.
ENDMETHOD.
METHOD create.
TRY.
DATA(lv_xml) = z2ui5_cl_fw_utility=>trans_object_2_xml( REF #( db ) ).
CATCH cx_xslt_serialization_error INTO DATA(x).
TRY.
DATA(ls_db) = db.
DATA(lo_app) = CAST object( ls_db-app ).
IF NOT line_exists( ls_db-t_attri[ check_ref_data = abap_true ] ).
RAISE EXCEPTION x.
ENDIF.
lo_app = CAST object( ls_db-app ).
LOOP AT ls_db-t_attri REFERENCE INTO DATA(lr_attri) WHERE check_ref_data = abap_true.
DATA(lv_assign) = 'LO_APP->' && lr_attri->name.
FIELD-SYMBOLS <attri> TYPE any.
FIELD-SYMBOLS <deref_attri> TYPE any.
ASSIGN (lv_assign) TO <attri>.
ASSIGN <attri>->* TO <deref_attri>.
lr_attri->data_rtti = z2ui5_cl_fw_utility=>rtti_get( <deref_attri> ).
CLEAR <deref_attri>.
CLEAR <attri>.
ENDLOOP.
lv_xml = z2ui5_cl_fw_utility=>trans_object_2_xml( REF #( ls_db ) ).
CATCH cx_root INTO DATA(x2).
RAISE EXCEPTION TYPE z2ui5_cl_fw_error
EXPORTING
val = x->get_text( ) && `<p>` && x->previous->get_text( ) && `<p>` && x2->get_text( ).
ENDTRY.
ENDTRY.
DATA(ls_draft) = VALUE z2ui5_t_draft( uuid = id
uuid_prev = db-id_prev
uuid_prev_app = db-id_prev_app
uuid_prev_app_stack = db-id_prev_app_stack
uname = z2ui5_cl_fw_utility=>get_user_tech( )
timestampl = z2ui5_cl_fw_utility=>get_timestampl( )
data = lv_xml ).
MODIFY z2ui5_t_draft FROM @ls_draft.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ).
COMMIT WORK AND WAIT.
ENDMETHOD.
METHOD load_app.
DATA(ls_db) = read( id ).
z2ui5_cl_fw_utility=>trans_xml_2_object(
EXPORTING
xml = ls_db-data
IMPORTING
data = result ).
LOOP AT result-t_attri TRANSPORTING NO FIELDS WHERE data_rtti <> ``.
DATA(lv_check_rtti) = abap_true.
ENDLOOP.
IF lv_check_rtti = abap_false.
RETURN.
ENDIF.
DATA(lo_app) = CAST object( result-app ) ##NEEDED.
LOOP AT result-t_attri REFERENCE INTO DATA(lr_attri) WHERE check_ref_data = abap_true.
FIELD-SYMBOLS <ref> TYPE any.
DATA(lv_assign) = 'LO_APP->' && lr_attri->name.
ASSIGN (lv_assign) TO <ref>.
z2ui5_cl_fw_utility=>rtti_set(
EXPORTING
rtti_data = lr_attri->data_rtti
IMPORTING
e_data = <ref> ).
CLEAR lr_attri->data_rtti.
ENDLOOP.
ENDMETHOD.
METHOD read.
IF check_load_app = abap_true.
SELECT SINGLE *
FROM z2ui5_t_draft
WHERE uuid = @id
INTO @result.
ELSE.
SELECT SINGLE uuid, uuid_prev, uuid_prev_app, uuid_prev_app_stack
FROM z2ui5_t_draft
WHERE uuid = @id
INTO CORRESPONDING FIELDS OF @result.
ENDIF.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ).
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>Z2UI5_CL_FW_DB</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abap2UI5 - database</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,62 @@
CLASS z2ui5_cl_fw_error DEFINITION INHERITING FROM cx_no_check
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
DATA:
BEGIN OF ms_error,
x_root TYPE REF TO cx_root,
uuid TYPE string,
text TYPE string,
END OF ms_error.
METHODS get_text REDEFINITION.
METHODS constructor
IMPORTING
val TYPE any OPTIONAL
previous TYPE REF TO cx_root OPTIONAL
PREFERRED PARAMETER val.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS z2ui5_cl_fw_error IMPLEMENTATION.
METHOD constructor ##ADT_SUPPRESS_GENERATION.
super->constructor( previous = previous ).
CLEAR textid.
TRY.
ms_error-x_root ?= val.
CATCH cx_root.
ms_error-text = val.
ENDTRY.
ms_error-uuid = z2ui5_cl_fw_utility=>get_uuid( ).
ENDMETHOD.
METHOD get_text.
IF ms_error-x_root IS NOT INITIAL.
result = ms_error-x_root->get_text( ).
DATA(error) = abap_true.
ELSEIF ms_error-text IS NOT INITIAL.
result = ms_error-text.
error = abap_true.
ENDIF.
result = COND #( WHEN error = abap_true AND result IS INITIAL THEN `unknown error` else result ).
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>Z2UI5_CL_FW_ERROR</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abap2UI5 - error</DESCRIPT>
<CATEGORY>40</CATEGORY>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,563 @@
CLASS z2ui5_cl_fw_handler DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
CONSTANTS:
BEGIN OF cs_bind_type,
one_way TYPE string VALUE 'ONE_WAY',
two_way TYPE string VALUE 'TWO_WAY',
one_time TYPE string VALUE 'ONE_TIME',
END OF cs_bind_type.
TYPES:
BEGIN OF ty_s_next2,
t_scroll TYPE z2ui5_if_client=>ty_t_name_value,
title TYPE string,
search TYPE string,
BEGIN OF s_view,
xml TYPE string,
check_destroy TYPE abap_bool,
check_update_model TYPE abap_bool,
END OF s_view,
BEGIN OF s_view_nest,
xml TYPE string,
id TYPE string,
method_insert TYPE string,
method_destroy TYPE string,
check_destroy TYPE abap_bool,
check_update_model TYPE abap_bool,
END OF s_view_nest,
BEGIN OF s_popup,
xml TYPE string,
id TYPE string,
check_destroy TYPE abap_bool,
check_update_model TYPE abap_bool,
END OF s_popup,
BEGIN OF s_popover,
xml TYPE string,
id TYPE string,
open_by_id TYPE string,
check_destroy TYPE abap_bool,
check_update_model TYPE abap_bool,
END OF s_popover,
BEGIN OF s_cursor,
id TYPE string,
cursorpos TYPE string,
selectionstart TYPE string,
selectionend TYPE string,
END OF s_cursor,
BEGIN OF s_timer,
interval_ms TYPE string,
event_finished TYPE string,
action_finished TYPE string,
END OF s_timer,
BEGIN OF s_msg_box,
type TYPE string,
text TYPE string,
END OF s_msg_box,
BEGIN OF s_msg_toast,
text TYPE string,
END OF s_msg_toast,
_viewmodel TYPE string,
END OF ty_s_next2.
TYPES:
BEGIN OF ty_s_next,
o_app_call TYPE REF TO z2ui5_if_app,
o_app_leave TYPE REF TO z2ui5_if_app,
s_set TYPE ty_s_next2,
END OF ty_s_next.
CLASS-DATA ss_config TYPE z2ui5_if_client=>ty_s_config.
CLASS-DATA so_body TYPE REF TO z2ui5_cl_fw_utility_json.
DATA ms_db TYPE z2ui5_cl_fw_db=>ty_s_db.
DATA ms_actual TYPE z2ui5_if_client=>ty_s_get.
DATA ms_next TYPE ty_s_next.
CLASS-METHODS request_begin
IMPORTING
body TYPE string
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_handler.
METHODS request_end
RETURNING
VALUE(result) TYPE string.
METHODS _create_binding
IMPORTING
value TYPE data
type TYPE string DEFAULT cs_bind_type-two_way
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS set_app_start
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_handler.
CLASS-METHODS set_app_client
IMPORTING
id_prev TYPE clike
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_handler.
METHODS set_app_leave
IMPORTING
check_no_db_save TYPE abap_bool DEFAULT abap_false
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_handler.
METHODS set_app_call
IMPORTING
check_no_db_save TYPE abap_bool DEFAULT abap_false
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_handler.
CLASS-METHODS set_app_system
IMPORTING
VALUE(ix) TYPE REF TO cx_root OPTIONAL
error_text TYPE string OPTIONAL
PREFERRED PARAMETER ix
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_handler.
CLASS-METHODS model_set_backend
IMPORTING
model TYPE REF TO data
app TYPE REF TO object
t_attri TYPE z2ui5_cl_fw_utility=>ty_t_attri.
CLASS-METHODS model_set_frontend
IMPORTING
app TYPE REF TO object
t_attri TYPE z2ui5_cl_fw_utility=>ty_t_attri
RETURNING
VALUE(result) TYPE string.
METHODS app_set_next
IMPORTING
app TYPE REF TO z2ui5_if_app
RETURNING
VALUE(r_result) TYPE REF TO z2ui5_cl_fw_handler.
ENDCLASS.
CLASS Z2UI5_CL_FW_HANDLER IMPLEMENTATION.
METHOD app_set_next.
app->id = COND #( WHEN app->id IS INITIAL THEN z2ui5_cl_fw_utility=>get_uuid( ) ELSE app->id ).
r_result = NEW #( ).
r_result->ms_db-app = app.
r_result->ms_db-id = app->id.
r_result->ms_db-id_prev = ms_db-id.
r_result->ms_db-id_prev_app = ms_db-id.
r_result->ms_db-t_attri = z2ui5_cl_fw_utility=>get_t_attri_by_ref( app ).
r_result->ms_actual-check_launchpad_active = ms_actual-check_launchpad_active.
r_result->ms_actual-check_on_navigated = abap_true.
r_result->ms_next-s_set = ms_next-s_set.
ENDMETHOD.
METHOD model_set_backend.
DATA(lo_app) = CAST object( app ) ##NEEDED.
DATA(lr_model) = CAST data( model ) ##NEEDED.
LOOP AT t_attri REFERENCE INTO DATA(lr_attri) WHERE bind_type = cs_bind_type-two_way.
TRY.
DATA(lv_type_kind) = lr_attri->type_kind.
FIELD-SYMBOLS <backend> TYPE any.
DATA(lv_name) = `LO_APP->` && lr_attri->name.
ASSIGN (lv_name) TO <backend>.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ).
FIELD-SYMBOLS <frontend> TYPE any.
lv_name = `LR_MODEL->` && replace( val = lr_attri->name
sub = `-`
with = `_`
occ = 0 ).
ASSIGN (lv_name) TO <frontend>.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ).
IF lr_attri->check_ref_data IS NOT INITIAL.
ASSIGN <backend>->* TO <backend>.
TRY.
DATA(lo_tab) = CAST cl_abap_tabledescr( cl_abap_datadescr=>describe_by_data( <backend> ) ) ##NEEDED.
lv_type_kind = `h`.
CATCH cx_root.
ENDTRY.
ENDIF.
CASE lv_type_kind.
WHEN `h`.
z2ui5_cl_fw_utility=>trans_ref_tab_2_tab(
EXPORTING
ir_tab_from = <frontend>
IMPORTING
t_result = <backend> ).
WHEN OTHERS.
ASSIGN <frontend>->* TO <frontend>.
CASE lr_attri->type_kind.
WHEN 'D' OR 'T'.
/ui2/cl_json=>deserialize(
EXPORTING
json = `"` && <frontend> && `"`
CHANGING
data = <backend> ).
WHEN OTHERS.
<backend> = <frontend>.
ENDCASE.
ENDCASE.
CATCH cx_root.
ENDTRY.
ENDLOOP.
ENDMETHOD.
METHOD model_set_frontend.
DATA(lo_app) = CAST object( app ) ##NEEDED.
DATA(lr_view_model) = z2ui5_cl_fw_utility_json=>factory( ).
DATA(lo_update) = lr_view_model->add_attribute_object( ss_config-view_model_edit_name ).
LOOP AT t_attri REFERENCE INTO DATA(lr_attri) WHERE bind_type <> ``.
IF lr_attri->bind_type = cs_bind_type-one_time.
lr_view_model->add_attribute( n = lr_attri->name
v = lr_attri->data_stringify
apos_active = abap_false ).
CONTINUE.
ENDIF.
DATA(lo_actual) = COND #( WHEN lr_attri->bind_type = cs_bind_type-one_way
THEN lr_view_model
ELSE lo_update ).
FIELD-SYMBOLS <attribute> TYPE any.
DATA(lv_name) = `LO_APP->` && to_upper( lr_attri->name ).
ASSIGN (lv_name) TO <attribute>.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ).
CASE lr_attri->type_kind.
WHEN `h`.
lo_actual->add_attribute( n = lr_attri->name
v = z2ui5_cl_fw_utility=>trans_any_2_json( <attribute> )
apos_active = abap_false ).
WHEN OTHERS.
CASE lr_attri->type.
WHEN `ABAP_BOOL` OR `ABAP_BOOLEAN` OR `XSDBOOLEAN`.
lo_actual->add_attribute( n = lr_attri->name
v = SWITCH #( <attribute>
WHEN abap_true THEN `true` ELSE `false` )
apos_active = abap_false ).
WHEN OTHERS.
lo_actual->add_attribute( n = lr_attri->name
v = /ui2/cl_json=>serialize( <attribute> )
apos_active = abap_false ).
ENDCASE.
ENDCASE.
ENDLOOP.
result = lr_view_model->stringify( ).
ENDMETHOD.
METHOD request_begin.
so_body = z2ui5_cl_fw_utility_json=>factory( body ).
TRY.
DATA(location) = so_body->get_attribute( `OLOCATION` ).
ss_config-body = body.
ss_config-search = location->get_attribute( `SEARCH` )->get_val( ).
ss_config-origin = location->get_attribute( `ORIGIN` )->get_val( ).
ss_config-pathname = location->get_attribute( `PATHNAME` )->get_val( ).
ss_config-version = location->get_attribute( `VERSION` )->get_val( ).
CATCH cx_root.
ENDTRY.
ss_config-view_model_edit_name = `oUpdate`.
TRY.
DATA(lv_id_prev) = so_body->get_attribute( `ID` )->get_val( ).
result = set_app_client( lv_id_prev ).
result->ms_actual-check_on_navigated = abap_false.
CATCH cx_root.
result = set_app_start( ).
result->ms_actual-check_on_navigated = abap_true.
ENDTRY.
TRY.
FIELD-SYMBOLS <any> TYPE any.
ASSIGN ('SO_BODY->MR_ACTUAL') TO <any>.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ).
ASSIGN ('<ANY>->ARGUMENTS') TO <any>.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ).
ASSIGN ('<ANY>->*') TO <any>.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ).
FIELD-SYMBOLS <arg> TYPE STANDARD TABLE.
ASSIGN <any> TO <arg>.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ).
FIELD-SYMBOLS <arg_row> TYPE any.
LOOP AT <arg> ASSIGNING <arg_row>.
IF sy-tabix = 1.
FIELD-SYMBOLS <val> TYPE any.
ASSIGN ('<ARG_ROW>->EVENT->*') TO <val>.
result->ms_actual-event = <val>.
ELSE.
ASSIGN <arg_row>->* TO <val>.
INSERT <val> INTO TABLE result->ms_actual-t_event_arg.
ENDIF.
ENDLOOP.
CATCH cx_root.
ENDTRY.
TRY.
DATA(lo_scroll) = so_body->get_attribute( `OSCROLL` ).
z2ui5_cl_fw_utility=>trans_ref_tab_2_tab(
EXPORTING
ir_tab_from = lo_scroll->mr_actual
IMPORTING
t_result = result->ms_actual-t_scroll_pos ).
CATCH cx_root.
ENDTRY.
TRY.
DATA(lo_cursor) = so_body->get_attribute( `OCURSOR` ).
result->ms_actual-s_cursor-id = lo_cursor->get_attribute( `ID` )->get_val( ).
CATCH cx_root.
ENDTRY.
IF ss_config-search CS `scenario=LAUNCHPAD`.
result->ms_actual-check_launchpad_active = abap_true.
ENDIF.
ENDMETHOD.
METHOD request_end.
DATA(lo_resp) = z2ui5_cl_fw_utility_json=>factory( ).
DATA(lv_viewmodel) = COND #( WHEN ms_next-s_set-_viewmodel IS NOT INITIAL
THEN ms_next-s_set-_viewmodel
ELSE model_set_frontend( app = ms_db-app
t_attri = ms_db-t_attri ) ).
lo_resp->add_attribute( n = `OVIEWMODEL`
v = lv_viewmodel
apos_active = abap_false ).
lo_resp->add_attribute( n = `PARAMS`
v = z2ui5_cl_fw_utility=>trans_any_2_json( ms_next-s_set )
apos_active = abap_false ).
lo_resp->add_attribute( n = `ID`
v = ms_db-id ).
IF ms_next-s_set-search IS INITIAL.
lo_resp->add_attribute( n = `SEARCH`
v = ms_actual-s_config-search ).
ELSE.
lo_resp->add_attribute( n = `SEARCH`
v = ms_next-s_set-search ).
ENDIF.
result = lo_resp->mo_root->stringify( ).
z2ui5_cl_fw_db=>create( id = ms_db-id
db = ms_db ).
ENDMETHOD.
METHOD set_app_call.
result = app_set_next( ms_next-o_app_call ).
result->ms_db-id_prev_app_stack = ms_db-id.
CLEAR ms_next.
IF check_no_db_save = abap_false.
z2ui5_cl_fw_db=>create( id = ms_db-id
db = ms_db ).
ENDIF.
ENDMETHOD.
METHOD set_app_client.
result = NEW #( ).
result->ms_db = z2ui5_cl_fw_db=>load_app( id_prev ).
result->ms_db-id = z2ui5_cl_fw_utility=>get_uuid( ).
result->ms_db-id_prev = id_prev.
TRY.
model_set_backend( model = so_body->get_attribute( ss_config-view_model_edit_name )->mr_actual
app = result->ms_db-app
t_attri = result->ms_db-t_attri ).
CATCH cx_root.
ENDTRY.
ENDMETHOD.
METHOD set_app_leave.
result = app_set_next( ms_next-o_app_leave ).
TRY.
DATA(ls_draft) = z2ui5_cl_fw_db=>read( id = result->ms_db-id
check_load_app = abap_false ).
result->ms_db-id_prev_app_stack = ls_draft-uuid_prev_app_stack.
CATCH cx_root.
result->ms_db-id_prev_app_stack = ms_db-id_prev_app_stack.
ENDTRY.
CLEAR ms_next.
IF check_no_db_save = abap_false.
z2ui5_cl_fw_db=>create( id = ms_db-id
db = ms_db ).
ENDIF.
ENDMETHOD.
METHOD set_app_start.
TRY.
DATA(lv_classname) = to_upper( so_body->get_attribute( 'APP_START' )->get_val( ) ).
lv_classname = shift_left( val = lv_classname
sub = cl_abap_char_utilities=>horizontal_tab ).
lv_classname = shift_right( val = lv_classname
sub = cl_abap_char_utilities=>horizontal_tab ).
CATCH cx_root.
ENDTRY.
IF lv_classname IS INITIAL.
lv_classname = z2ui5_cl_fw_utility=>url_param_get( val = `app_start` url = ss_config-search ).
ENDIF.
IF lv_classname IS INITIAL.
result = set_app_system( ).
RETURN.
ENDIF.
TRY.
result = NEW #( ).
result->ms_db-id = z2ui5_cl_fw_utility=>get_uuid( ).
lv_classname = z2ui5_cl_fw_utility=>get_trim_upper( lv_classname ).
CREATE OBJECT result->ms_db-app TYPE (lv_classname).
result->ms_db-app->id = result->ms_db-id.
result->ms_db-t_attri = z2ui5_cl_fw_utility=>get_t_attri_by_ref( result->ms_db-app ).
CATCH cx_root.
result = set_app_system( error_text = `App with name ` && lv_classname && ` not found...` ).
ENDTRY.
ENDMETHOD.
METHOD set_app_system.
result = NEW #( ).
result->ms_db-id = z2ui5_cl_fw_utility=>get_uuid( ).
IF ix IS NOT BOUND AND error_text IS NOT INITIAL.
ix = NEW z2ui5_cl_fw_error( val = error_text ).
ENDIF.
IF ix IS BOUND.
result->ms_next-o_app_call = z2ui5_cl_fw_app=>factory_error( ix ).
result = result->set_app_call( abap_true ).
RETURN.
ENDIF.
result->ms_db-app = z2ui5_cl_fw_app=>factory_start( ).
result->ms_db-t_attri = z2ui5_cl_fw_utility=>get_t_attri_by_ref( result->ms_db-app ).
result->ms_db-app->id = result->ms_db-id.
ENDMETHOD.
METHOD _create_binding.
DATA(lo_app) = CAST object( ms_db-app ) ##NEEDED.
DATA lr_in TYPE REF TO data.
GET REFERENCE OF value INTO lr_in.
LOOP AT ms_db-t_attri REFERENCE INTO DATA(lr_attri)
WHERE bind_type <> cs_bind_type-one_time.
FIELD-SYMBOLS <attribute> TYPE any.
DATA(lv_name) = `LO_APP->` && to_upper( lr_attri->name ).
ASSIGN (lv_name) TO <attribute>.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 )
v = `Attribute in App with name ` && lv_name && ` not found` ).
DATA lr_ref TYPE REF TO data.
GET REFERENCE OF <attribute> INTO lr_ref.
IF lr_attri->check_ref_data IS NOT INITIAL.
FIELD-SYMBOLS <field> TYPE any.
ASSIGN lr_ref->* TO <field>.
lr_ref = CAST data( <field> ).
ENDIF.
IF lr_in = lr_ref.
IF lr_attri->bind_type IS NOT INITIAL AND lr_attri->bind_type <> type.
z2ui5_cl_fw_utility=>raise(
`<p>Binding Error - Two different binding types for same attribute used (` && lr_attri->name && `).` ).
ENDIF.
IF strlen( lr_attri->name ) > 30.
z2ui5_cl_fw_utility=>raise(
`<p>Binding Error - Name of attribute more than 30 characters: ` && lr_attri->name ).
ENDIF.
lr_attri->bind_type = type.
result = COND #( WHEN type = cs_bind_type-two_way THEN `/` && ss_config-view_model_edit_name && `/` ELSE `/` ) && lr_attri->name.
RETURN.
ENDIF.
ENDLOOP.
IF type = cs_bind_type-two_way.
z2ui5_cl_fw_utility=>raise( `Binding Error - Two way binding used but no attribute found` ).
ENDIF.
DATA(lv_id) = z2ui5_cl_fw_utility=>get_uuid( ).
INSERT VALUE #( name = lv_id
data_stringify = z2ui5_cl_fw_utility=>trans_any_2_json( value )
bind_type = cs_bind_type-one_time )
INTO TABLE ms_db-t_attri.
result = |/{ lv_id }|.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,45 @@
CLASS ltcl_unit_test DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL critical.
PRIVATE SECTION.
METHODS test_req_begin_fw_start FOR TESTING RAISING cx_static_check.
METHODS test_req_begin_app_start FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_test IMPLEMENTATION.
METHOD test_req_begin_fw_start.
DATA(lv_body) = `{"OLOCATION":{"ORIGIN":"https:/url.abap-web.us10.hana.ondemand.com","PATHNAME":"/sap/bc/http/sap/z_http_service_for_ui","SEARCH":"?sap-client=100","VERSION":"com.sap.ui5.dist:sapui5-sdk-dist:1.115.0:war"}}`.
DATA(lo_handler) = z2ui5_cl_fw_handler=>request_begin( lv_body ).
IF lo_handler->ms_db-app IS NOT BOUND.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
DATA(lo_app_fw) = CAST z2ui5_cl_fw_app( lo_handler->ms_db-app ) ##NEEDED.
ENDMETHOD.
METHOD test_req_begin_app_start.
DATA(lv_body) = `{"OLOCATION":{"ORIGIN":"https://url.abap-web.us10.hana.ondemand.com","PATHNAME":"/sap/bc/http/sap/z_http_service_for_ui","SEARCH":"?sap-client=100&app_start=z2ui5_cl_app_hello_world","VERSION":"c` &&
`om.sap.ui5.dist:sapui5-sdk-dist:1.115.0:war"}}`.
DATA(lo_handler) = z2ui5_cl_fw_handler=>request_begin( lv_body ).
IF lo_handler->ms_db-app IS NOT BOUND.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
DATA(lo_app_fw) = CAST z2ui5_cl_app_hello_world( lo_handler->ms_db-app ) ##NEEDED.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>Z2UI5_CL_FW_HANDLER</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abap2UI5 - handler</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,151 @@
CLASS z2ui5_cl_fw_integration_test DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
DATA product TYPE string.
DATA quantity TYPE string.
DATA check_initialized TYPE abap_bool.
CLASS-DATA sv_state TYPE string.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS Z2UI5_CL_FW_INTEGRATION_TEST IMPLEMENTATION.
METHOD z2ui5_if_app~main.
IF check_initialized = abap_false.
check_initialized = abap_true.
product = 'tomato'.
quantity = '500'.
ENDIF.
CASE client->get( )-event.
WHEN 'BUTTON_POST'.
client->message_toast_display( |{ product } { quantity } - send to the server| ).
WHEN 'BACK'.
client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app_stack ) ).
ENDCASE.
IF sv_state = 'TEST_MESSAGE_BOX'.
client->message_box_display( 'test message box' ).
ENDIF.
IF sv_state = 'TEST_MESSAGE_TOAST'.
client->message_toast_display( 'test message toast' ).
ENDIF.
CASE sv_state.
WHEN 'TEST_ONE_WAY'.
client->view_display( z2ui5_cl_xml_view=>factory( client )->shell(
)->page( title = 'abap2UI5 - First Example'
navbuttonpress = client->_event( 'BACK' )
shownavbutton = abap_true
)->simple_form( title = 'Form Title'
editable = abap_true
)->content( 'form'
)->title( 'Input'
)->label( 'quantity'
)->input( client->_bind( quantity )
)->label( 'product'
)->input( value = product
enabled = abap_false
)->button( text = 'post'
press = client->_event( 'BUTTON_POST' )
)->get_root( )->xml_get( ) ).
WHEN 'TEST_POPUP'.
client->popup_display( z2ui5_cl_xml_view=>factory( client
)->dialog( title = 'abap2UI5 - First Example'
)->simple_form( title = 'Form Title'
editable = abap_true
)->content( 'form'
)->title( 'Input'
)->label( 'quantity'
)->input( client->_bind_edit( quantity )
)->label( 'product'
)->input( value = product
enabled = abap_false
)->button( text = 'post'
press = client->_event( 'BUTTON_POST' )
)->get_root( )->xml_get( ) ).
WHEN 'TEST_TIMER'.
client->timer_set( event_finished = 'TIMER_FINISHED'
interval_ms = `500` ).
client->view_display( z2ui5_cl_xml_view=>factory( client )->shell(
)->page( title = 'abap2UI5 - First Example'
navbuttonpress = client->_event( 'BACK' )
shownavbutton = abap_true
)->simple_form( title = 'Form Title'
editable = abap_true
)->content( 'form'
)->title( 'Input'
)->label( 'quantity'
)->input( client->_bind( quantity )
)->label( 'product'
)->input( value = product
enabled = abap_false
)->button( text = 'post'
press = client->_event( 'BUTTON_POST' )
)->get_root( )->xml_get( ) ).
WHEN OTHERS.
client->view_display( z2ui5_cl_xml_view=>factory( client )->shell(
)->page( title = 'abap2UI5 - First Example'
navbuttonpress = client->_event( 'BACK' )
shownavbutton = abap_true
)->simple_form( title = 'Form Title'
editable = abap_true
)->content( 'form'
)->title( 'Input'
)->label( 'quantity'
)->input( client->_bind_edit( quantity )
)->label( 'product'
)->input( value = product
enabled = abap_false
)->button( text = 'post'
press = client->_event( 'BUTTON_POST' )
)->get_root( )->xml_get( ) ).
ENDCASE.
IF sv_state = 'TEST_SCROLL_CURSOR'.
client->view_display( `test` ).
client->cursor_set( id = 'id_text2'
cursorpos = '5'
selectionstart = '5'
selectionend = '10' ).
client->scroll_position_set( VALUE #( v = '99999'
( n = 'id_page' )
( n = 'id_text3' ) ) ).
ENDIF.
IF sv_state = 'TEST_NAVIGATE'.
DATA(lo_app) = NEW z2ui5_cl_fw_integration_test( ).
sv_state = 'LEAVE_APP'.
client->nav_app_call( lo_app ).
RETURN.
ENDIF.
IF sv_state = 'LEAVE_APP'.
CLEAR sv_state.
client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app ) ).
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,362 @@
CLASS ltcl_unit_02_app_start DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL DANGEROUS.
PUBLIC SECTION.
PRIVATE SECTION.
METHODS test_index_html FOR TESTING RAISING cx_static_check.
METHODS test_xml_view FOR TESTING RAISING cx_static_check.
METHODS test_id FOR TESTING RAISING cx_static_check.
METHODS test_xml_popup FOR TESTING RAISING cx_static_check.
METHODS test_bind_one_way FOR TESTING RAISING cx_static_check.
METHODS test_bind_two_way FOR TESTING RAISING cx_static_check.
METHODS test_message_toast FOR TESTING RAISING cx_static_check.
METHODS test_message_box FOR TESTING RAISING cx_static_check.
METHODS test_timer FOR TESTING RAISING cx_static_check.
METHODS test_landing_page FOR TESTING RAISING cx_static_check.
METHODS test_scroll_cursor FOR TESTING RAISING cx_static_check.
METHODS test_navigate FOR TESTING RAISING cx_static_check.
METHODS test_startup_path FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_02_app_start IMPLEMENTATION.
METHOD test_xml_view.
z2ui5_cl_fw_integration_test=>sv_state = ``.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_VIEW->XML->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
<val> = shift_left( <val> ).
IF <val>(9) <> `<mvc:View`.
cl_abap_unit_assert=>fail( msg = 'xml view - intital view wrong'
quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_index_html.
DATA(lv_index_html) = z2ui5_cl_http_handler=>http_get( ).
IF lv_index_html IS INITIAL.
cl_abap_unit_assert=>fail( 'HTTP GET - index html initial' ).
ENDIF.
ENDMETHOD.
METHOD test_id.
z2ui5_cl_fw_integration_test=>sv_state = ``.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `ID->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> IS INITIAL.
cl_abap_unit_assert=>fail( msg = 'id - initial value is initial'
quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_bind_one_way.
DATA(lo_test) = NEW z2ui5_cl_fw_integration_test( ) ##NEEDED.
z2ui5_cl_fw_integration_test=>sv_state = `TEST_ONE_WAY`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `OVIEWMODEL->QUANTITY->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `500`.
cl_abap_unit_assert=>fail( msg = 'data binding - initial set oUpdate wrong'
quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_bind_two_way.
z2ui5_cl_fw_integration_test=>sv_state = ``.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `OVIEWMODEL->OUPDATE->QUANTITY->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `500`.
cl_abap_unit_assert=>fail( msg = 'data binding - initial set oUpdate wrong'
quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_message_box.
z2ui5_cl_fw_integration_test=>sv_state = `TEST_MESSAGE_BOX`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_MSG_BOX->TEXT->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `test message box`.
cl_abap_unit_assert=>fail( msg = 'message box - text wrong'
quit = 5 ).
ENDIF.
UNASSIGN <val>.
lv_assign = `PARAMS->S_MSG_BOX->TYPE->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `information`.
cl_abap_unit_assert=>fail( msg = 'message box - type wrong'
quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_message_toast.
z2ui5_cl_fw_integration_test=>sv_state = `TEST_MESSAGE_TOAST`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_MSG_TOAST->TEXT->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `test message toast`.
cl_abap_unit_assert=>fail( msg = 'message toast - text wrong'
quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_timer.
z2ui5_cl_fw_integration_test=>sv_state = `TEST_TIMER`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_TIMER->EVENT_FINISHED->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `TIMER_FINISHED`.
cl_abap_unit_assert=>fail( msg = 'timer - event wrong'
quit = 5 ).
ENDIF.
UNASSIGN <val>.
lv_assign = `PARAMS->S_TIMER->INTERVAL_MS->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `500`.
cl_abap_unit_assert=>fail( msg = 'timer - ms wrong'
quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_xml_popup.
z2ui5_cl_fw_integration_test=>sv_state = `TEST_POPUP`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_POPUP->XML->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
<val> = shift_left( <val> ).
IF <val>(9) <> `<mvc:View`.
cl_abap_unit_assert=>fail( msg = 'xml popup - intital popup wrong'
quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_landing_page.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : ""}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_VIEW->XML->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
<val> = shift_left( <val> ).
IF <val> NS `Step 4`.
cl_abap_unit_assert=>fail( msg = 'landing page - not started when no app'
quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_scroll_cursor.
z2ui5_cl_fw_integration_test=>sv_state = `TEST_SCROLL_CURSOR`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
ENDMETHOD.
METHOD test_startup_path.
z2ui5_cl_fw_integration_test=>sv_state = `TEST_NAVIGATE`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
ENDMETHOD.
METHOD test_navigate.
z2ui5_cl_fw_integration_test=>sv_state = `TEST_NAVIGATE`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
`{ "OLOCATION" : { "SEARCH" : "app_start=z2ui5_cl_fw_integration_test"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
ENDMETHOD.
ENDCLASS.
CLASS ltcl_unit_03_app_ajax DEFINITION FINAL FOR TESTING
DURATION LONG
RISK LEVEL DANGEROUS.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
DATA product TYPE string.
DATA quantity TYPE string.
DATA check_initialized TYPE abap_bool.
CLASS-DATA sv_state TYPE string.
PRIVATE SECTION.
METHODS test_app_change_value FOR TESTING RAISING cx_static_check.
METHODS test_app_event FOR TESTING RAISING cx_static_check.
METHODS test_app_dump FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_03_app_ajax IMPLEMENTATION.
METHOD z2ui5_if_app~main.
IF check_initialized = abap_false.
check_initialized = abap_true.
product = 'tomato'.
quantity = '500'.
ENDIF.
CASE client->get( )-event.
WHEN 'BUTTON_POST'.
client->message_toast_display( |{ product } { quantity } - send to the server| ).
WHEN 'BACK'.
client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app_stack ) ).
ENDCASE.
IF sv_state = 'ERROR'.
z2ui5_cl_fw_utility=>raise( `exception test` ).
ENDIF.
client->view_display( z2ui5_cl_xml_view=>factory( client )->shell(
)->page( title = 'abap2UI5 - First Example'
navbuttonpress = client->_event( 'BACK' )
shownavbutton = abap_true
)->simple_form( title = 'Form Title'
editable = abap_true
)->content( 'form'
)->title( 'Input'
)->label( 'quantity'
)->input( client->_bind( quantity )
)->label( 'product'
)->input( value = product
enabled = abap_false
)->button( text = 'post'
press = client->_event( 'BUTTON_POST' )
)->get_root( )->xml_get( ) ).
ENDMETHOD.
METHOD test_app_change_value.
ENDMETHOD.
METHOD test_app_event.
ENDMETHOD.
METHOD test_app_dump.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>Z2UI5_CL_FW_INTEGRATION_TEST</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abap2UI5 - integration test</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,569 @@
CLASS z2ui5_cl_fw_utility DEFINITION PUBLIC
CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_attri,
name TYPE string,
type_kind TYPE string,
type TYPE string,
bind_type TYPE string,
data_stringify TYPE string,
data_rtti TYPE string,
check_ref_data TYPE abap_bool,
END OF ty_attri.
TYPES ty_t_attri TYPE STANDARD TABLE OF ty_attri WITH EMPTY KEY.
CLASS-METHODS url_param_get
IMPORTING
val TYPE string
url TYPE string
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS url_param_create_url
IMPORTING
t_params TYPE z2ui5_if_client=>ty_t_name_value
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS url_param_set
IMPORTING
url TYPE string
name TYPE string
value TYPE string
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS get_classname_by_ref
IMPORTING
in TYPE REF TO object
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS raise
IMPORTING
v TYPE clike DEFAULT `CX_SY_SUBRC`
when TYPE abap_bool DEFAULT abap_true
PREFERRED PARAMETER v.
CLASS-METHODS get_uuid
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS get_user_tech
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS trans_any_2_json
IMPORTING
any TYPE any
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS trans_xml_2_object
IMPORTING
xml TYPE clike
EXPORTING
data TYPE data.
CLASS-METHODS get_t_attri_by_ref
IMPORTING
io_app TYPE REF TO object
RETURNING
VALUE(result) TYPE ty_t_attri ##NEEDED.
CLASS-METHODS trans_object_2_xml
IMPORTING
object TYPE data
RETURNING
VALUE(result) TYPE string
RAISING
cx_xslt_serialization_error.
CLASS-METHODS get_abap_2_json
IMPORTING
val TYPE any
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS check_is_boolean
IMPORTING
val TYPE any
RETURNING
VALUE(result) TYPE abap_bool.
CLASS-METHODS get_json_boolean
IMPORTING
val TYPE any
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS trans_ref_tab_2_tab
IMPORTING
ir_tab_from TYPE REF TO data
EXPORTING
t_result TYPE STANDARD TABLE.
CLASS-METHODS get_trim_upper
IMPORTING val TYPE any
RETURNING VALUE(result) TYPE string.
CLASS-METHODS _get_t_attri_by_struc
IMPORTING
io_app TYPE REF TO object
iv_attri TYPE csequence
RETURNING
VALUE(result) TYPE abap_attrdescr_tab.
CLASS-METHODS rtti_get
IMPORTING
data TYPE any
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS rtti_set
IMPORTING
rtti_data TYPE string
EXPORTING
e_data TYPE REF TO data.
CLASS-METHODS get_timestampl
RETURNING
VALUE(result) TYPE timestampl.
CLASS-METHODS get_replace
IMPORTING
iv_val TYPE clike
iv_begin TYPE clike
iv_end TYPE clike
iv_replace TYPE clike DEFAULT ''
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS get_trim
IMPORTING
val TYPE any
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS get_trim_lower
IMPORTING
val TYPE any
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS url_param_get_tab
IMPORTING
i_val TYPE string
RETURNING
VALUE(rt_params) TYPE z2ui5_if_client=>ty_t_name_value.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS z2ui5_cl_fw_utility IMPLEMENTATION.
METHOD check_is_boolean.
TRY.
DATA(lo_ele) = CAST cl_abap_elemdescr( cl_abap_elemdescr=>describe_by_data( val ) ).
CASE lo_ele->get_relative_name( ).
WHEN `ABAP_BOOL` OR `XSDBOOLEAN`.
result = abap_true.
ENDCASE.
CATCH cx_root.
ENDTRY.
ENDMETHOD.
METHOD get_abap_2_json.
IF check_is_boolean( val ).
result = COND #( WHEN val = abap_true THEN `true` ELSE `false` ).
ELSE.
result = |"{ escape( val = val
format = cl_abap_format=>e_json_string ) }"|.
ENDIF.
ENDMETHOD.
METHOD get_classname_by_ref.
DATA(lv_classname) = cl_abap_classdescr=>get_class_name( in ).
result = substring_after( val = lv_classname
sub = `\CLASS=` ).
ENDMETHOD.
METHOD get_json_boolean.
IF check_is_boolean( val ).
result = COND #( WHEN val = abap_true THEN `true` ELSE `false` ).
ELSE.
result = val.
ENDIF.
ENDMETHOD.
METHOD get_replace.
result = iv_val.
DATA(lv_1) = substring_before( val = result
sub = iv_begin ).
DATA(lv_2) = substring_after( val = result
sub = iv_end ).
result = COND #( WHEN lv_2 IS NOT INITIAL THEN lv_1 && iv_replace && lv_2 ).
ENDMETHOD.
METHOD get_timestampl.
GET TIME STAMP FIELD result.
ENDMETHOD.
METHOD get_trim.
result = shift_left( shift_right( CONV string( val ) ) ).
result = shift_right( val = result sub = cl_abap_char_utilities=>horizontal_tab ).
result = shift_left( val = result sub = cl_abap_char_utilities=>horizontal_tab ).
result = shift_left( shift_right( CONV string( val ) ) ).
ENDMETHOD.
METHOD get_trim_lower.
result = to_lower( get_trim( CONV string( val ) ) ).
ENDMETHOD.
METHOD get_trim_upper.
result = to_upper( get_trim( CONV string( val ) ) ).
ENDMETHOD.
METHOD get_t_attri_by_ref.
DATA(lt_attri) = CAST cl_abap_classdescr( cl_abap_objectdescr=>describe_by_object_ref( io_app ) )->attributes.
DELETE lt_attri WHERE visibility <> cl_abap_classdescr=>public.
LOOP AT lt_attri INTO DATA(ls_attri)
WHERE type_kind = cl_abap_classdescr=>typekind_struct2
OR type_kind = cl_abap_classdescr=>typekind_struct1.
DELETE lt_attri INDEX sy-tabix.
INSERT LINES OF _get_t_attri_by_struc( io_app = io_app
iv_attri = ls_attri-name ) INTO TABLE lt_attri.
ENDLOOP.
LOOP AT lt_attri INTO ls_attri.
DATA(ls_attri2) = VALUE ty_attri( ).
ls_attri2 = CORRESPONDING #( ls_attri ).
APPEND ls_attri2 TO result.
ENDLOOP.
ENDMETHOD.
METHOD get_user_tech.
result = sy-uname.
ENDMETHOD.
METHOD get_uuid.
TRY.
DATA uuid TYPE c LENGTH 32.
TRY.
CALL METHOD (`CL_SYSTEM_UUID`)=>if_system_uuid_static~create_uuid_c32
RECEIVING
uuid = uuid.
CATCH cx_sy_dyn_call_illegal_class.
DATA(lv_fm) = `GUID_CREATE`.
CALL FUNCTION lv_fm
IMPORTING
ev_guid_32 = uuid.
ENDTRY.
result = uuid.
CATCH cx_root.
ASSERT 1 = 0.
ENDTRY.
ENDMETHOD.
METHOD raise.
IF when = abap_true.
RAISE EXCEPTION TYPE z2ui5_cl_fw_error EXPORTING val = v.
ENDIF.
ENDMETHOD.
METHOD rtti_get.
TRY.
DATA srtti TYPE REF TO object.
CALL METHOD ('ZCL_SRTTI_TYPEDESCR')=>('CREATE_BY_DATA_OBJECT')
EXPORTING
data_object = data
RECEIVING
srtti = srtti.
CALL TRANSFORMATION id SOURCE srtti = srtti dobj = data RESULT XML result.
CATCH cx_root.
DATA(lv_link) = `https://github.com/sandraros/S-RTTI`.
DATA(lv_text) = `<p>Please install the open-source project S-RTTI by sandraros and try again: <a href="` &&
lv_link && `" style="color:blue; font-weight:600;">(link)</a></p>`.
RAISE EXCEPTION TYPE z2ui5_cl_fw_error
EXPORTING
val = lv_text.
ENDTRY.
ENDMETHOD.
METHOD rtti_set.
TRY.
DATA srtti TYPE REF TO object.
CALL TRANSFORMATION id SOURCE XML rtti_data RESULT srtti = srtti.
DATA rtti_type TYPE REF TO cl_abap_typedescr.
CALL METHOD srtti->('GET_RTTI')
RECEIVING
rtti = rtti_type.
DATA lo_datadescr TYPE REF TO cl_abap_datadescr.
lo_datadescr ?= rtti_type.
CREATE DATA e_data TYPE HANDLE lo_datadescr.
ASSIGN e_data->* TO FIELD-SYMBOL(<variable>).
CALL TRANSFORMATION id SOURCE XML rtti_data RESULT dobj = <variable>.
CATCH cx_root.
DATA(lv_link) = `https://github.com/sandraros/S-RTTI`.
DATA(lv_text) = `<p>Please install the open-source project S-RTTI by sandraros and try again: <a href="` && lv_link && `" style="color:blue; font-weight:600;">(link)</a></p>`.
RAISE EXCEPTION TYPE z2ui5_cl_fw_error
EXPORTING
val = lv_text.
ENDTRY.
ENDMETHOD.
METHOD trans_any_2_json.
result = /ui2/cl_json=>serialize( any ).
ENDMETHOD.
METHOD trans_object_2_xml.
FIELD-SYMBOLS <object> TYPE any.
ASSIGN object->* TO <object>.
raise( when = xsdbool( sy-subrc <> 0 ) ).
CALL TRANSFORMATION id
SOURCE data = <object>
RESULT XML result
OPTIONS data_refs = `heap-or-create`.
ENDMETHOD.
METHOD trans_ref_tab_2_tab.
TYPES ty_t_ref TYPE STANDARD TABLE OF REF TO data.
FIELD-SYMBOLS <lt_from> TYPE ty_t_ref.
ASSIGN ir_tab_from->* TO <lt_from>.
raise( when = xsdbool( sy-subrc <> 0 ) ).
CLEAR t_result.
DATA(lo_tab) = CAST cl_abap_tabledescr( cl_abap_datadescr=>describe_by_data( t_result ) ).
DATA(lo_struc) = CAST cl_abap_structdescr( lo_tab->get_table_line_type( ) ).
DATA(lt_components) = lo_struc->get_components( ).
LOOP AT <lt_from> INTO DATA(lr_from).
DATA lr_row TYPE REF TO data.
CREATE DATA lr_row TYPE HANDLE lo_struc.
ASSIGN lr_row->* TO FIELD-SYMBOL(<row>).
IF sy-subrc <> 0.
EXIT.
ENDIF.
ASSIGN lr_from->* TO FIELD-SYMBOL(<row_ui5>).
raise( when = xsdbool( sy-subrc <> 0 ) ).
LOOP AT lt_components INTO DATA(ls_comp).
FIELD-SYMBOLS <comp> TYPE data.
ASSIGN COMPONENT ls_comp-name OF STRUCTURE <row> TO <comp>.
IF sy-subrc <> 0.
EXIT.
ENDIF.
FIELD-SYMBOLS <comp_ui5> TYPE data.
ASSIGN COMPONENT ls_comp-name OF STRUCTURE <row_ui5> TO <comp_ui5>.
IF sy-subrc <> 0.
EXIT.
ENDIF.
ASSIGN <comp_ui5>->* TO FIELD-SYMBOL(<ls_data_ui5>).
IF sy-subrc = 0.
CASE ls_comp-type->kind.
WHEN cl_abap_typedescr=>kind_table.
trans_ref_tab_2_tab( EXPORTING ir_tab_from = <comp_ui5>
IMPORTING t_result = <comp> ).
WHEN OTHERS.
<comp> = <ls_data_ui5>.
ENDCASE.
ENDIF.
ENDLOOP.
INSERT <row> INTO TABLE t_result.
ENDLOOP.
ENDMETHOD.
METHOD trans_xml_2_object.
CALL TRANSFORMATION id
SOURCE XML xml
RESULT data = data.
ENDMETHOD.
METHOD url_param_create_url.
LOOP AT t_params INTO DATA(ls_param).
result = result && ls_param-n && `=` && ls_param-v && `&`.
ENDLOOP.
result = shift_right( val = result
sub = `&` ).
ENDMETHOD.
METHOD url_param_get.
DATA(lt_params) = url_param_get_tab( url ).
DATA(lv_val) = get_trim_lower( val ).
result = VALUE #( lt_params[ n = lv_val ]-v OPTIONAL ).
ENDMETHOD.
METHOD url_param_get_tab.
DATA(lv_search) = replace( val = i_val sub = `%3D` with = '=' occ = 0 ).
lv_search = shift_left( val = lv_search sub = `?` ).
lv_search = get_trim_lower( lv_search ).
DATA(lv_search2) = substring_after( val = lv_search
sub = `&sap-startup-params=` ).
lv_search = COND #( WHEN lv_search2 IS NOT INITIAL THEN lv_search2 ELSE lv_search ).
lv_search2 = substring_after( val = get_trim_lower( lv_search ) sub = `?` ).
IF lv_search2 IS NOT INITIAL.
lv_search = lv_search2.
ENDIF.
SPLIT lv_search AT `&` INTO TABLE DATA(lt_param).
LOOP AT lt_param REFERENCE INTO DATA(lr_param).
SPLIT lr_param->* AT `=` INTO DATA(lv_name) DATA(lv_value).
INSERT VALUE #( n = get_trim_lower( lv_name ) v = get_trim_lower( lv_value ) ) INTO TABLE rt_params.
ENDLOOP.
ENDMETHOD.
METHOD url_param_set.
DATA(lt_params) = url_param_get_tab( url ).
DATA(lv_n) = get_trim_lower( name ).
LOOP AT lt_params REFERENCE INTO DATA(lr_params)
WHERE n = lv_n.
lr_params->v = get_trim_lower( value ).
ENDLOOP.
IF sy-subrc <> 0.
INSERT VALUE #( n = lv_n v = get_trim_lower( value ) ) INTO TABLE lt_params.
ENDIF.
result = url_param_create_url( lt_params ).
ENDMETHOD.
METHOD _get_t_attri_by_struc.
FIELD-SYMBOLS <attribute> TYPE any.
DATA(lv_name) = `IO_APP->` && to_upper( iv_attri ).
ASSIGN (lv_name) TO <attribute>.
raise( when = xsdbool( sy-subrc <> 0 ) ).
DATA(lo_type) = cl_abap_structdescr=>describe_by_data( <attribute> ).
DATA(lo_struct) = CAST cl_abap_structdescr( lo_type ).
LOOP AT lo_struct->get_components( ) REFERENCE INTO DATA(lr_comp).
DATA(lv_element) = iv_attri && `-` && lr_comp->name.
IF lr_comp->as_include = abap_true.
INSERT LINES OF _get_t_attri_by_struc( io_app = io_app
iv_attri = lv_element ) INTO TABLE result.
ELSE.
INSERT VALUE #( name = lv_element
type_kind = lr_comp->type->type_kind ) INTO TABLE result.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,576 @@
CLASS ltcl_test_app DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_row,
title TYPE string,
value TYPE string,
descr TYPE string,
icon TYPE string,
info TYPE string,
selected TYPE abap_bool,
checkbox TYPE abap_bool,
END OF ty_row.
CONSTANTS sv_status TYPE string VALUE `test` ##NEEDED.
CLASS-DATA sv_var TYPE string.
CLASS-DATA ss_tab TYPE ty_row.
CLASS-DATA st_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
DATA mv_val TYPE string ##NEEDED.
DATA ms_tab TYPE ty_row ##NEEDED.
DATA mt_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY ##NEEDED.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ltcl_test_app IMPLEMENTATION.
ENDCLASS.
CLASS ltcl_unit_test_sap_api DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS check_input
IMPORTING
val TYPE data
RETURNING
VALUE(result) TYPE abap_bool.
METHODS test_assign FOR TESTING RAISING cx_static_check.
METHODS test_eledescr_rel_name FOR TESTING RAISING cx_static_check.
METHODS test_classdescr FOR TESTING RAISING cx_static_check.
METHODS test_substring_after FOR TESTING RAISING cx_static_check.
METHODS test_substring_before FOR TESTING RAISING cx_static_check.
METHODS test_string_shift FOR TESTING RAISING cx_static_check.
METHODS test_string_replace FOR TESTING RAISING cx_static_check.
METHODS test_raise_error FOR TESTING RAISING cx_static_check.
METHODS test_xsdbool FOR TESTING RAISING cx_static_check.
METHODS test_xsdbool_nested FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_test DEFINITION FINAL FOR TESTING
DURATION MEDIUM
RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS test_check_is_boolean FOR TESTING RAISING cx_static_check.
METHODS test_get_abap_2_json FOR TESTING RAISING cx_static_check.
METHODS test_create FOR TESTING RAISING cx_static_check.
METHODS test_get_classname_by_ref FOR TESTING RAISING cx_static_check.
METHODS test_get_json_boolean FOR TESTING RAISING cx_static_check.
METHODS test_get_replace FOR TESTING RAISING cx_static_check.
METHODS test_get_timestampl FOR TESTING RAISING cx_static_check.
METHODS test_get_trim_lower FOR TESTING RAISING cx_static_check.
METHODS test_get_trim_upper FOR TESTING RAISING cx_static_check.
METHODS test_attri_by_ref FOR TESTING RAISING cx_static_check.
METHODS test_get_uuid FOR TESTING RAISING cx_static_check.
METHODS test_get_user_tech FOR TESTING RAISING cx_static_check.
METHODS test_raise FOR TESTING RAISING cx_static_check.
METHODS test_any_2_json FOR TESTING RAISING cx_static_check.
METHODS test_any_2_json_02 FOR TESTING RAISING cx_static_check.
METHODS test_trans_ref_tab_2_tab FOR TESTING RAISING cx_static_check.
METHODS test_url_param_create_url FOR TESTING RAISING cx_static_check.
METHODS test_url_param_get FOR TESTING RAISING cx_static_check.
METHODS test_url_param_get_tab FOR TESTING RAISING cx_static_check.
METHODS url_param_set FOR TESTING RAISING cx_static_check.
METHODS test_raise_error_not FOR TESTING RAISING cx_static_check.
METHODS test_raise_error FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_test_sap_api IMPLEMENTATION.
METHOD test_assign.
DATA(lo_app) = NEW ltcl_test_app( ).
lo_app->mv_val = `ABC`.
FIELD-SYMBOLS <any> TYPE any.
DATA(lv_assign) = `LO_APP->` && 'MV_VAL'.
ASSIGN (lv_assign) TO <any>.
cl_abap_unit_assert=>assert_equals(
act = <any>
exp = `ABC` ).
ENDMETHOD.
METHOD test_classdescr.
DATA(lo_app) = NEW ltcl_test_app( ).
DATA(lt_attri) = CAST cl_abap_classdescr( cl_abap_objectdescr=>describe_by_object_ref( lo_app ) )->attributes.
DATA(lv_test) = lt_attri[ name = `MS_TAB` ].
lv_test = lt_attri[ name = `MT_TAB` ].
lv_test = lt_attri[ name = `MV_VAL` ].
lv_test = lt_attri[ name = `SS_TAB` ].
lv_test = lt_attri[ name = `ST_TAB` ].
lv_test = lt_attri[ name = `SV_STATUS` ].
lv_test = lt_attri[ name = `SV_VAR` ].
ENDMETHOD.
METHOD test_eledescr_rel_name.
DATA(lo_ele) = CAST cl_abap_elemdescr( cl_abap_elemdescr=>describe_by_data( abap_true ) ).
cl_abap_unit_assert=>assert_equals(
act = lo_ele->get_relative_name( )
exp = `ABAP_BOOL` ).
ENDMETHOD.
METHOD test_substring_after.
cl_abap_unit_assert=>assert_equals(
act = substring_after( val = 'this is a string' sub = 'a' )
exp = ` string` ).
ENDMETHOD.
METHOD test_substring_before.
cl_abap_unit_assert=>assert_equals(
act = substring_before( val = 'this is a string' sub = 'a' )
exp = `this is ` ).
ENDMETHOD.
METHOD test_string_shift.
cl_abap_unit_assert=>assert_equals(
act = shift_left( shift_right( val = ` string ` sub = ` ` ) )
exp = `string` ).
ENDMETHOD.
METHOD test_string_replace.
DATA(lv_search) = replace( val = `one two three` sub = `two` with = 'ABC' occ = 0 ).
cl_abap_unit_assert=>assert_equals(
act = replace( val = `one two three` sub = `two` with = 'ABC' occ = 0 )
exp = `one ABC three` ).
ENDMETHOD.
METHOD test_raise_error.
TRY.
RAISE EXCEPTION TYPE z2ui5_cl_fw_error.
cl_abap_unit_assert=>fail( ).
CATCH z2ui5_cl_fw_error INTO DATA(lx).
cl_abap_unit_assert=>assert_bound( lx ).
ENDTRY.
ENDMETHOD.
METHOD test_xsdbool.
DATA(lv_xsdbool) = xsdbool( 1 = 1 ).
IF lv_xsdbool = abap_false.
cl_abap_unit_assert=>assert_equals(
act = lv_xsdbool
exp = abap_false ).
ENDIF.
IF xsdbool( 1 = 1 ) = abap_false.
cl_abap_unit_assert=>fail( ).
ENDIF.
ENDMETHOD.
METHOD test_xsdbool_nested.
DATA(lv_xsdbool) = check_input( xsdbool( 1 = 1 ) ).
IF lv_xsdbool = abap_false.
cl_abap_unit_assert=>assert_equals(
act = lv_xsdbool
exp = abap_false ).
ENDIF.
IF check_input( abap_false ).
cl_abap_unit_assert=>fail( ).
ENDIF.
IF check_input( xsdbool( 1 = 1 ) ) = abap_false.
cl_abap_unit_assert=>fail( ).
ENDIF.
IF check_input( xsdbool( 2 = 1 ) ).
cl_abap_unit_assert=>fail( ).
ENDIF.
ENDMETHOD.
METHOD check_input.
result = val.
ENDMETHOD.
ENDCLASS.
CLASS ltcl_unit_test IMPLEMENTATION.
METHOD test_attri_by_ref.
"dummy for abaplint check green
ltcl_test_app=>sv_var = ``.
ltcl_test_app=>ss_tab = VALUE #( ).
ltcl_test_app=>st_tab = VALUE #( ).
DATA(lo_app) = NEW ltcl_test_app( ).
DATA(lt_attri) = z2ui5_cl_fw_utility=>get_t_attri_by_ref( lo_app ).
DATA(lt_attri_result) = VALUE z2ui5_cl_fw_utility=>ty_t_attri(
( name = `MT_TAB` type_kind = `h` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `MV_VAL` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `ST_TAB` type_kind = `h` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `SV_STATUS` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `SV_VAR` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `MS_TAB-TITLE` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `MS_TAB-VALUE` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `MS_TAB-DESCR` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `MS_TAB-ICON` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `MS_TAB-INFO` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `MS_TAB-SELECTED` type_kind = `C` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `MS_TAB-CHECKBOX` type_kind = `C` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `SS_TAB-TITLE` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `SS_TAB-VALUE` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `SS_TAB-DESCR` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `SS_TAB-ICON` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `SS_TAB-INFO` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `SS_TAB-SELECTED` type_kind = `C` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `SS_TAB-CHECKBOX` type_kind = `C` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
).
IF lt_attri_result <> lt_attri.
cl_abap_unit_assert=>fail( msg = 'utility - create t_attri failed'
quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_check_is_boolean.
DATA(lv_bool) = xsdbool( 1 = 1 ).
cl_abap_unit_assert=>assert_equals(
act = z2ui5_cl_fw_utility=>check_is_boolean( lv_bool )
exp = abap_true ).
lv_bool = xsdbool( 1 = 2 ).
cl_abap_unit_assert=>assert_equals(
act = z2ui5_cl_fw_utility=>check_is_boolean( lv_bool )
exp = abap_true ).
cl_abap_unit_assert=>assert_equals(
act = z2ui5_cl_fw_utility=>check_is_boolean( abap_true )
exp = abap_true ).
cl_abap_unit_assert=>assert_equals(
act = z2ui5_cl_fw_utility=>check_is_boolean( abap_false )
exp = abap_true ).
ENDMETHOD.
METHOD test_create.
DATA(lo_test) = NEW z2ui5_cl_fw_utility( ) ##NEEDED.
ENDMETHOD.
METHOD test_get_abap_2_json.
DATA(lv_bool) = xsdbool( 1 = 1 ).
cl_abap_unit_assert=>assert_equals( exp = `true` act = z2ui5_cl_fw_utility=>get_abap_2_json( lv_bool ) ).
lv_bool = xsdbool( 1 = 2 ).
cl_abap_unit_assert=>assert_equals( exp = `false` act = z2ui5_cl_fw_utility=>get_abap_2_json( lv_bool ) ).
ENDMETHOD.
METHOD test_get_classname_by_ref.
DATA(lo_test) = NEW z2ui5_cl_fw_utility( ).
DATA(lv_name) = z2ui5_cl_fw_utility=>get_classname_by_ref( lo_test ).
IF lv_name <> `Z2UI5_CL_FW_UTILITY`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
DATA(lo_test2) = NEW ltcl_test_app( ).
DATA(lv_name2) = z2ui5_cl_fw_utility=>get_classname_by_ref( lo_test2 ).
IF lv_name2 <> `LTCL_TEST_APP`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_get_json_boolean.
IF `false` <> z2ui5_cl_fw_utility=>get_json_boolean( abap_false ).
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
IF `ABCD` <> z2ui5_cl_fw_utility=>get_json_boolean( `ABCD` ).
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_get_replace.
DATA(lv_text) = `this is a replace text`.
DATA(lv_result) = z2ui5_cl_fw_utility=>get_replace(
iv_val = lv_text
iv_begin = `is a `
iv_end = ` te`
iv_replace = 'is a test te' ).
IF lv_result <> `this is a test text`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_get_timestampl.
DATA(lv_time) = z2ui5_cl_fw_utility=>get_timestampl( ).
DATA(lv_time2) = z2ui5_cl_fw_utility=>get_timestampl( ).
IF lv_time2 < lv_time.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_get_trim_lower.
IF z2ui5_cl_fw_utility=>get_trim_lower( ` JsadfHHs ` ) <> `jsadfhhs`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_get_trim_upper.
IF z2ui5_cl_fw_utility=>get_trim_upper( ` JsadfHHs ` ) <> `JSADFHHS`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_get_uuid.
DATA(lv_uuid) = z2ui5_cl_fw_utility=>get_uuid( ).
IF lv_uuid IS INITIAL.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
IF strlen( lv_uuid ) <> 32.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_get_user_tech.
IF sy-uname <> z2ui5_cl_fw_utility=>get_user_tech( ).
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_raise.
TRY.
z2ui5_cl_fw_utility=>raise( ).
cl_abap_unit_assert=>fail( quit = 5 ).
CATCH cx_root.
ENDTRY.
TRY.
z2ui5_cl_fw_utility=>raise( when = xsdbool( 1 = 1 ) ).
cl_abap_unit_assert=>fail( quit = 5 ).
CATCH cx_root.
ENDTRY.
TRY.
z2ui5_cl_fw_utility=>raise( when = xsdbool( 1 = 3 ) ).
CATCH cx_root.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDTRY.
ENDMETHOD.
METHOD test_any_2_json.
TYPES:
BEGIN OF ty_row,
title TYPE string,
value TYPE string,
selected TYPE abap_bool,
END OF ty_row.
TYPES ty_t_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
DATA(lt_tab) = VALUE ty_t_tab( ( title = 'Test' value = 'this is a description' selected = abap_true )
( title = 'Test2' value = 'this is a new descr' selected = abap_false ) ).
DATA(lv_tab_json) = z2ui5_cl_fw_utility=>trans_any_2_json( lt_tab ).
DATA(lv_result) = `[{"TITLE":"Test","VALUE":"this is a description","SELECTED":true},{"TITLE":"Test2","VALUE":"this is a new descr","SELECTED":false}]`.
IF lv_result <> lv_tab_json.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_any_2_json_02.
TYPES:
BEGIN OF ty_row,
title TYPE string,
value TYPE string,
selected TYPE abap_bool,
END OF ty_row.
TYPES ty_t_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
DATA(lt_tab) = VALUE ty_t_tab( ( title = 'Test' value = 'this is a description' selected = abap_true )
( title = 'Test2' value = 'this is a new descr' selected = abap_false ) ).
DATA(lt_tab2) = VALUE ty_t_tab( ).
DATA(lv_tab) = z2ui5_cl_fw_utility=>trans_any_2_json( lt_tab ).
/ui2/cl_json=>deserialize( EXPORTING json = lv_tab
CHANGING data = lt_tab2 ).
IF lt_tab <> lt_tab2.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_trans_ref_tab_2_tab.
TYPES:
BEGIN OF ty_row,
title TYPE string,
value TYPE string,
selected TYPE abap_bool,
END OF ty_row.
TYPES ty_t_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
DATA(lv_result) = `[{"TITLE":"Test","VALUE":"this is a description","SELECTED":true},{"TITLE":"Test2","VALUE":"this is a new descr","SELECTED":false}]`.
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_result
CHANGING data = lo_data ).
DATA(lt_tab2) = VALUE ty_t_tab( ).
z2ui5_cl_fw_utility=>trans_ref_tab_2_tab(
EXPORTING ir_tab_from = lo_data
IMPORTING t_result = lt_tab2 ).
DATA(lt_tab) = VALUE ty_t_tab( ( title = 'Test' value = 'this is a description' selected = abap_true )
( title = 'Test2' value = 'this is a new descr' selected = abap_false ) ).
IF lt_tab <> lt_tab2.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_url_param_create_url.
DATA(lt_param) = z2ui5_cl_fw_utility=>url_param_get_tab( `https://url.com/rvice_for_ui?sap-client=100&app_start=z2ui5_cl_app_hello_world` ).
DATA(lv_url) = z2ui5_cl_fw_utility=>url_param_create_url( lt_param ).
IF lv_url <> `sap-client=100&app_start=z2ui5_cl_app_hello_world`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_url_param_get.
DATA(lv_param) = z2ui5_cl_fw_utility=>url_param_get(
val = `app_start`
url = `https://url.com/rvice_for_ui?sap-client=100&app_start=z2ui5_cl_app_hello_world` ).
IF lv_param <> `z2ui5_cl_app_hello_world`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_url_param_get_tab.
DATA(lt_param) = z2ui5_cl_fw_utility=>url_param_get_tab( `https://url.com/rvice_for_ui?sap-client=100&app_start=z2ui5_cl_app_hello_world` ).
IF lt_param[ n = `sap-client` ]-v <> `100`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
IF lt_param[ n = `app_start` ]-v <> `z2ui5_cl_app_hello_world`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD url_param_set.
DATA(lv_param) = z2ui5_cl_fw_utility=>url_param_set(
name = `app_start`
value = `z2ui5_cl_app_hello_world2`
url = `https://url.com/rvice_for_ui?sap-client=100&app_start=z2ui5_cl_app_hello_world` ).
IF lv_param <> `sap-client=100&app_start=z2ui5_cl_app_hello_world2`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_raise_error.
TRY.
z2ui5_cl_fw_utility=>raise( `error occured` ).
cl_abap_unit_assert=>fail( ).
CATCH z2ui5_cl_fw_error INTO DATA(lx).
* cl_abap_unit_assert=>assert_equals(
* act = lx->get_text( )
* exp = `error occured` ).
ENDTRY.
ENDMETHOD.
METHOD test_raise_error_not.
TRY.
z2ui5_cl_fw_utility=>raise( when = xsdbool( 1 = 2 ) ).
CATCH z2ui5_cl_fw_error INTO DATA(lx).
cl_abap_unit_assert=>fail( quit = 5 ).
ENDTRY.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>Z2UI5_CL_FW_UTILITY</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abap2UI5 - utility</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -0,0 +1,231 @@
CLASS z2ui5_cl_fw_utility_json DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
DATA mo_root TYPE REF TO z2ui5_cl_fw_utility_json.
DATA mo_parent TYPE REF TO z2ui5_cl_fw_utility_json.
DATA mv_name TYPE string.
DATA mv_value TYPE string.
DATA mt_values TYPE STANDARD TABLE OF REF TO z2ui5_cl_fw_utility_json WITH EMPTY KEY.
DATA mr_actual TYPE REF TO data.
DATA mv_apost_active TYPE abap_bool.
CLASS-METHODS factory
IMPORTING
iv_json TYPE clike OPTIONAL
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json.
METHODS constructor.
METHODS get_attribute
IMPORTING
name TYPE string
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json.
METHODS get_val
RETURNING
VALUE(result) TYPE string.
METHODS get_val_ref
RETURNING
VALUE(result) TYPE REF TO data.
METHODS add_attribute
IMPORTING
n TYPE clike
v TYPE clike
apos_active TYPE abap_bool DEFAULT abap_true
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json.
METHODS add_attribute_object
IMPORTING
name TYPE clike
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json.
METHODS add_attribute_struc
IMPORTING
val TYPE data
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json.
METHODS add_attribute_instance
IMPORTING
val TYPE REF TO z2ui5_cl_fw_utility_json
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json.
METHODS stringify
RETURNING
VALUE(result) TYPE string.
PROTECTED SECTION.
CLASS-METHODS new
IMPORTING
io_root TYPE REF TO z2ui5_cl_fw_utility_json
iv_name TYPE simple
RETURNING
VALUE(result) TYPE REF TO z2ui5_cl_fw_utility_json.
PRIVATE SECTION.
ENDCLASS.
CLASS Z2UI5_CL_FW_UTILITY_JSON IMPLEMENTATION.
METHOD add_attribute.
result = new( io_root = mo_root
iv_name = n ).
result->mv_value = COND #( WHEN apos_active = abap_true
THEN escape( val = v
format = cl_abap_format=>e_json_string ) ELSE v ).
result->mv_apost_active = apos_active.
result->mo_parent = me.
INSERT result INTO TABLE mt_values.
ENDMETHOD.
METHOD add_attribute_instance.
val->mo_root = mo_root.
val->mo_parent = me.
INSERT val INTO TABLE mt_values.
result = val.
ENDMETHOD.
METHOD add_attribute_object.
result = new( io_root = mo_root
iv_name = name ).
INSERT result INTO TABLE mt_values.
result->mo_parent = me.
ENDMETHOD.
METHOD add_attribute_struc.
FIELD-SYMBOLS <value> TYPE any.
DATA(lo_struc) = CAST cl_abap_structdescr( cl_abap_datadescr=>describe_by_data( val ) ).
DATA(lt_comp) = lo_struc->get_components( ).
LOOP AT lt_comp REFERENCE INTO DATA(lr_comp).
ASSIGN COMPONENT lr_comp->name OF STRUCTURE val TO <value>.
add_attribute( n = lr_comp->name
v = <value> ).
ENDLOOP.
result = me.
ENDMETHOD.
METHOD constructor.
mo_root = me.
ENDMETHOD.
METHOD factory.
result = NEW #( ).
result->mo_root = result.
/ui2/cl_json=>deserialize(
EXPORTING
json = CONV string( iv_json )
assoc_arrays = abap_true
CHANGING
data = result->mr_actual ).
ENDMETHOD.
METHOD get_attribute.
z2ui5_cl_fw_utility=>raise( when = xsdbool( mr_actual IS INITIAL ) ).
result = new( io_root = mo_root
iv_name = name ).
DATA(lv_name) = 'MR_ACTUAL->' && replace( val = name
sub = `-`
with = `_`
occ = 0 ).
FIELD-SYMBOLS <attribute> TYPE any.
ASSIGN (lv_name) TO <attribute>.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 ) ).
result->mr_actual = <attribute>.
result->mo_parent = me.
INSERT result INTO TABLE mt_values.
ENDMETHOD.
METHOD get_val.
FIELD-SYMBOLS <attribute> TYPE any.
ASSIGN mr_actual->* TO <attribute>.
z2ui5_cl_fw_utility=>raise( when = xsdbool( sy-subrc <> 0 )
v = `value of attribute in JSON not found` ).
result = <attribute>.
ENDMETHOD.
METHOD get_val_ref.
result = mr_actual.
ENDMETHOD.
METHOD new.
result = NEW #( ).
result->mo_root = io_root.
result->mv_name = CONV string( iv_name ).
ENDMETHOD.
METHOD stringify.
LOOP AT mt_values INTO DATA(lo_attri).
IF sy-tabix > 1.
result = result && `,`.
ENDIF.
result = |{ result }"{ lo_attri->mv_name }":|.
IF lo_attri->mt_values IS NOT INITIAL.
result = result && lo_attri->stringify( ).
ELSEIF lo_attri->mv_apost_active = abap_true OR lo_attri->mv_value IS INITIAL.
result = result && `"` && lo_attri->mv_value && `"`.
ELSE.
result = result && lo_attri->mv_value.
ENDIF.
ENDLOOP.
result = `{` && result && `}`.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,79 @@
CLASS ltcl_unit_01_json DEFINITION FINAL FOR TESTING
DURATION medium
RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS test_json_attri FOR TESTING RAISING cx_static_check.
METHODS test_json_object FOR TESTING RAISING cx_static_check.
METHODS test_json_struc FOR TESTING RAISING cx_static_check.
METHODS test_create_json FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_01_json IMPLEMENTATION.
METHOD test_json_attri.
DATA(lo_tree) = NEW z2ui5_cl_fw_utility_json( ).
lo_tree->add_attribute( n = `AAA`
v = `BBB` ).
DATA(lv_result) = lo_tree->stringify( ).
IF `{"AAA":"BBB"}` <> lv_result.
cl_abap_unit_assert=>fail( 'json tree - wrong stringify attributes' ).
ENDIF.
ENDMETHOD.
METHOD test_json_object.
DATA(lo_tree) = NEW z2ui5_cl_fw_utility_json( ).
lo_tree->add_attribute_object( `CCC` )->add_attribute( n = `AAA`
v = `BBB` ).
DATA(lv_result) = lo_tree->stringify( ).
IF `{"CCC":{"AAA":"BBB"}}` <> lv_result.
cl_abap_unit_assert=>fail( 'json tree - wrong stringify object attributes' ).
ENDIF.
ENDMETHOD.
METHOD test_json_struc.
DATA(lo_tree) = NEW z2ui5_cl_fw_utility_json( ).
TYPES:
BEGIN OF ty_s_test,
comp1 TYPE string,
comp2 TYPE string,
END OF ty_s_test.
DATA(ls_test) = VALUE ty_s_test( comp1 = `AAA` comp2 = `BBB` ).
lo_tree->add_attribute_object( `CCC` )->add_attribute_struc( ls_test ).
DATA(lv_result) = lo_tree->stringify( ).
IF `{"CCC":{"COMP1":"AAA","COMP2":"BBB"}}` <> lv_result.
cl_abap_unit_assert=>fail( 'json tree - wrong stringify structure' ).
ENDIF.
ENDMETHOD.
METHOD test_create_json.
DATA(lo_json) = z2ui5_cl_fw_utility_json=>factory( `{"CCC":{"COMP1":"AAA","COMP2":"BBB"}}` ).
DATA(lo_attri) = lo_json->get_attribute( `CCC` )->get_attribute( `COMP2` ).
DATA(lr_ref) = lo_attri->get_val_ref( ).
IF lr_ref->* <> `BBB`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
DATA(lv_val) = lo_attri->get_val( ).
IF lv_val <> `BBB`.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>Z2UI5_CL_FW_UTILITY_JSON</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>abap2UI5 - utility json</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@ -4,6 +4,7 @@
<asx:values>
<DEVC>
<CTEXT>abap2UI5</CTEXT>
<TPCLASS>X</TPCLASS>
</DEVC>
</asx:values>
</asx:abap>

View File

@ -32,7 +32,8 @@ CLASS Z2UI5_CL_APP_HELLO_WORLD IMPLEMENTATION.
client->view_display( z2ui5_cl_xml_view=>factory( client
)->shell(
)->page( title = 'abap2UI5 - z2ui5_cl_app_hello_world'
)->simple_form( title = 'Hello World' editable = abap_true
)->simple_form( title = 'Hello World'
editable = abap_true
)->content( ns = `form`
)->title( 'Make an input here and send it to the server...'
)->label( 'quantity'

View File

@ -0,0 +1,19 @@
CLASS ltcl_unit_test DEFINITION FINAL FOR TESTING
DURATION long
RISK LEVEL CRITICAL.
PRIVATE SECTION.
METHODS first_test FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_test IMPLEMENTATION.
METHOD first_test.
DATA(lo_app) = NEW z2ui5_cl_app_hello_world( ) ##NEEDED.
ENDMETHOD.
ENDCLASS.

View File

@ -10,6 +10,7 @@
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
</asx:values>
</asx:abap>

View File

@ -4,6 +4,13 @@ CLASS z2ui5_cl_http_handler DEFINITION
PUBLIC SECTION.
CLASS-METHODS http_post
IMPORTING
body TYPE string
RETURNING
VALUE(result) TYPE string.
CLASS-METHODS http_get
IMPORTING
t_config TYPE z2ui5_if_client=>ty_t_name_value OPTIONAL
@ -13,12 +20,6 @@ CLASS z2ui5_cl_http_handler DEFINITION
RETURNING
VALUE(r_result) TYPE string.
CLASS-METHODS http_post
IMPORTING
body TYPE string
RETURNING
VALUE(result) TYPE string.
PROTECTED SECTION.
PRIVATE SECTION.
@ -31,7 +32,7 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION.
METHOD http_get.
DATA(lt_Config) = t_config.
DATA(lt_config) = t_config.
IF lt_config IS INITIAL.
lt_config = VALUE #(
@ -49,8 +50,7 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION.
ELSE.
lv_sec_policy = content_security_policy.
ENDIF.
z2ui5_lcl_fw_db=>cleanup( ).
z2ui5_cl_fw_db=>cleanup( ).
r_result = `<html>` && |\n| &&
`<head>` && |\n| &&
@ -76,12 +76,12 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION.
` <div id="content" data-handle-validation="true" ></div>` && |\n| &&
`</body>` && |\n| &&
`</html><abc/>` && |\n|.
r_result = r_result && `<script>` && |\n| &&
` sap.ui.getCore().attachInit(function () {` && |\n| &&
` "use strict";` && |\n| &&
|\n| &&
` sap.ui.controller("z2ui5_controller", {` && |\n| &&
|\n| &&
` onInit: function () {` && |\n| &&
|\n| &&
` // s type is String -> pattern: YYYY-MM-DDTHH:mm:ss ` && |\n| &&
@ -95,9 +95,7 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION.
|\n| &&
` // abap date and time to JS Date object => pattern: d = YYYYMMDD , t = HHmmss ` && |\n| &&
` Date.abapDateTimeToDateObject = ((d,t = '000000') => new Date(d.slice(0,4), (d[4]+d[5])-1, d[6]+d[7],t.slice(0,2),t.slice(2,4),t.slice(4,6)));` && |\n| &&
|\n| &&
` },` && |\n| &&
|\n| &&
` onAfterRendering: function () {` && |\n| &&
|\n| &&
` if (sap.z2ui5.oResponse.PARAMS.S_CURSOR.ID !== '') {` && |\n| &&
@ -214,7 +212,7 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION.
` }` && |\n| &&
` sap.z2ui5.oView.destroy();` && |\n| &&
` },` && |\n| &&
|\n| &&
` ` && |\n| &&
` onEventFrontend: (...args) => {` && |\n| &&
|\n| &&
` switch (args[0].EVENT) {` && |\n| &&
@ -244,6 +242,7 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION.
` if (sap.z2ui5.oViewPopup) {` && |\n| &&
` if (sap.z2ui5.oViewPopup.isOpen() == true) {` && |\n| &&
` sap.z2ui5.oBody.oUpdate = sap.z2ui5.oViewPopup.getModel().getData().oUpdate;` && |\n| &&
` // sap.z2ui5.oBody.oUpdate = sap.z2ui5.oView.getModel().getData().oUpdate;` && |\n| &&
` isUpdated = true;` && |\n| &&
` } }` && |\n| &&
` if ( isUpdated == false ) { ` && |\n| &&
@ -325,6 +324,7 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION.
|\n| &&
` new sap.ui.core.mvc.XMLView.create({` && |\n| &&
` definition: sap.z2ui5.oResponse.PARAMS.S_VIEW.XML,` && |\n| &&
` controller: sap.z2ui5.oController,` && |\n| &&
` }).then(oView => {` && |\n| &&
` oView.setModel(new sap.ui.model.json.JSONModel(sap.z2ui5.oResponse.OVIEWMODEL));` && |\n| &&
` if (sap.z2ui5.oParent) {` && |\n| &&
@ -401,15 +401,15 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION.
` sap.z2ui5.checkNestAfter = false;` && |\n| &&
|\n| &&
` jQuery.sap.require("sap.ui.core.Fragment");` && |\n| &&
` jQuery.sap.require("sap.ui.core.date.UI5Date");` && |\n| &&
` jQuery.sap.require("sap.m.MessageToast");` && |\n| &&
` jQuery.sap.require("sap.m.MessageBox");` && |\n| &&
` jQuery.sap.require("sap.ui.model.json.JSONModel");` && |\n| &&
` jQuery.sap.require("sap.ui.core.date.UI5Date");` && |\n| &&
|\n| &&
` var xml = atob('PA==') + 'mvc:View controllerName="z2ui5_controller" xmlns:mvc="sap.ui.core.mvc" /' + atob('Pg==');` && |\n| &&
` var oView = sap.ui.xmlview({ viewContent: xml });` && |\n| &&
` sap.z2ui5.oController = oView.getController();` && |\n| &&
` sap.z2ui5.checkLogActive = ` && z2ui5_lcl_utility=>get_json_boolean( check_logging ) && `;` && |\n| &&
` sap.z2ui5.checkLogActive = ` && z2ui5_cl_fw_utility=>get_json_boolean( check_logging ) && `;` && |\n| &&
` sap.z2ui5.oBody = {};` && |\n| &&
` sap.z2ui5.oBody.APP_START = sap.z2ui5.APP_START;` && |\n| &&
` sap.z2ui5.oController.Roundtrip();` && |\n| &&
@ -418,18 +418,17 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION.
`<abc/></html>`.
* ` sap.z2ui5.checkLogActive = ` && z2ui5_lcl_utility=>get_json_boolean( check_logging ) && `;` && |\n| &&
ENDMETHOD.
METHOD http_post.
DATA(lo_handler) = z2ui5_lcl_fw_handler=>request_begin( body ).
DATA(lo_handler) = z2ui5_cl_fw_handler=>request_begin( body ).
DO.
TRY.
ROLLBACK WORK.
CAST z2ui5_if_app( lo_handler->ms_db-o_app )->main( NEW z2ui5_lcl_fw_client( lo_handler ) ).
CAST z2ui5_if_app( lo_handler->ms_db-app )->main( NEW z2ui5_cl_fw_client( lo_handler ) ).
ROLLBACK WORK.
IF lo_handler->ms_next-o_app_leave IS NOT INITIAL.
@ -445,7 +444,7 @@ CLASS Z2UI5_CL_HTTP_HANDLER IMPLEMENTATION.
result = lo_handler->request_end( ).
CATCH cx_root INTO DATA(x).
lo_handler = z2ui5_lcl_fw_handler=>set_app_system( x ).
lo_handler = z2ui5_cl_fw_handler=>set_app_system( x ).
CONTINUE.
ENDTRY.

File diff suppressed because it is too large Load Diff

View File

@ -1,951 +1,24 @@
CLASS ltcl_unit_01_json DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS test_json_attri FOR TESTING RAISING cx_static_check.
METHODS test_json_object FOR TESTING RAISING cx_static_check.
METHODS test_json_struc FOR TESTING RAISING cx_static_check.
METHODS test_json_trans FOR TESTING RAISING cx_static_check.
METHODS test_json_trans_gen FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_01_utility DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS test_util_uuid_session FOR TESTING RAISING cx_static_check.
METHODS test_util_04_attri_by_ref FOR TESTING RAISING cx_static_check.
METHODS test_util_01_get_classdescr FOR TESTING RAISING cx_static_check.
METHODS test_util_02_get_attri FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_04_deep_data DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
DATA check_initialized TYPE abap_bool.
TYPES:
BEGIN OF ty_row,
title TYPE string,
value TYPE string,
descr TYPE string,
icon TYPE string,
info TYPE string,
selected TYPE abap_bool,
checkbox TYPE abap_bool,
END OF ty_row.
CLASS-DATA t_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
CLASS-DATA sv_status TYPE string.
PRIVATE SECTION.
METHODS test_app_deep_data FOR TESTING RAISING cx_static_check.
METHODS test_app_deep_data_change FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_01_json IMPLEMENTATION.
METHOD test_json_attri.
DATA(lo_tree) = NEW z2ui5_lcl_utility_tree_json( ).
lo_tree->add_attribute( n = `AAA` v = `BBB` ).
DATA(lv_result) = lo_tree->stringify( ).
IF `{"AAA":"BBB"}` <> lv_result.
cl_abap_unit_assert=>fail( 'json tree - wrong stringify attributes' ).
ENDIF.
ENDMETHOD.
METHOD test_json_object.
DATA(lo_tree) = NEW z2ui5_lcl_utility_tree_json( ).
lo_tree->add_attribute_object( `CCC` )->add_attribute( n = `AAA` v = `BBB` ).
DATA(lv_result) = lo_tree->stringify( ).
IF `{"CCC":{"AAA":"BBB"}}` <> lv_result.
cl_abap_unit_assert=>fail( 'json tree - wrong stringify object attributes' ).
ENDIF.
ENDMETHOD.
METHOD test_json_struc.
DATA(lo_tree) = NEW z2ui5_lcl_utility_tree_json( ).
TYPES:
BEGIN OF ty_s_test,
comp1 TYPE string,
comp2 TYPE string,
END OF ty_s_test.
DATA(ls_test) = VALUE ty_S_test( comp1 = `AAA` comp2 = `BBB` ).
lo_tree->add_attribute_object( `CCC` )->add_attribute_struc( ls_test ).
DATA(lv_result) = lo_tree->stringify( ).
IF `{"CCC":{"COMP1":"AAA","COMP2":"BBB"}}` <> lv_result.
cl_abap_unit_assert=>fail( 'json tree - wrong stringify structure' ).
ENDIF.
ENDMETHOD.
METHOD test_json_trans.
TYPES:
BEGIN OF ty_row,
title TYPE string,
value TYPE string,
selected TYPE abap_bool,
END OF ty_row.
TYPES ty_t_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
DATA(lt_tab) = VALUE ty_t_tab( ( title = 'Test' value = 'this is a description' selected = abap_true )
( title = 'Test2' value = 'this is a new descr' selected = abap_false ) ).
DATA(lt_tab2) = VALUE ty_t_tab( ).
DATA(lv_tab) = z2ui5_lcl_utility=>trans_any_2_json( lt_tab ).
/ui2/cl_json=>deserialize( EXPORTING json = lv_tab
CHANGING data = lt_tab2 ).
IF lt_tab <> lt_tab2.
cl_abap_unit_assert=>fail( msg = 'json serial - /ui2/cl_json wrong simple table' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_json_trans_gen.
TYPES:
BEGIN OF ty_row,
title TYPE string,
value TYPE string,
selected TYPE abap_bool,
END OF ty_row.
TYPES ty_t_tab TYPE STANDARD TABLE OF ty_row WITH EMPTY KEY.
DATA(lt_tab) = VALUE ty_t_tab( ( title = 'Test' value = 'this is a description' selected = abap_true )
( title = 'Test2' value = 'this is a new descr' selected = abap_false ) ).
DATA(lt_tab2) = VALUE ty_t_tab( ).
DATA(lv_tab) = z2ui5_lcl_utility=>trans_any_2_json( lt_tab ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_tab
CHANGING data = lo_data ).
z2ui5_lcl_utility=>trans_ref_tab_2_tab( EXPORTING ir_tab_from = lo_data
IMPORTING t_result = lt_tab2 ).
IF lt_tab <> lt_tab2.
cl_abap_unit_assert=>fail( msg = 'json serial - /ui2/cl_json wrong generic table' quit = 5 ).
ENDIF.
ENDMETHOD.
ENDCLASS.
CLASS ltcl_unit_01_utility IMPLEMENTATION.
METHOD test_util_04_attri_by_ref.
DATA(lo_app) = NEW ltcl_unit_04_deep_data( ).
DATA(lt_attri) = z2ui5_lcl_utility=>get_t_attri_by_ref( lo_app ).
DATA(lt_attri_result) = VALUE z2ui5_lcl_utility=>ty_t_attri(
( name = `Z2UI5_IF_APP~ID` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `CHECK_INITIALIZED` type_kind = `C` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `SV_STATUS` type_kind = `g` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
( name = `T_TAB` type_kind = `h` type = `` bind_type = `` data_stringify = `` data_rtti = `` check_ref_data = '' )
).
IF lt_attri_result <> lt_attri.
cl_abap_unit_assert=>fail( msg = 'utility - create t_attri failed' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_util_uuid_session.
DATA(lv_one) = z2ui5_lcl_utility=>get_uuid_session( ).
DATA(lv_two) = z2ui5_lcl_utility=>get_uuid_session( ).
IF lv_one <> `1`.
cl_abap_unit_assert=>fail( msg = 'utility - create session id' quit = 5 ).
ENDIF.
IF lv_two <> `2`.
cl_abap_unit_assert=>fail( msg = 'utility - create session id' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_util_02_get_attri.
DATA(lo_app) = NEW ltcl_unit_04_deep_data( ).
lo_app->sv_status = `ABC`.
FIELD-SYMBOLS <any> TYPE any.
DATA(lv_assign) = `LO_APP->` && 'SV_STATUS'.
ASSIGN (lv_assign) TO <any>.
IF <any> <> `ABC`.
cl_abap_unit_assert=>fail( msg = 'utility - assign of attribute from outside not working' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_util_01_get_classdescr.
DATA(lo_app) = NEW ltcl_unit_04_deep_data( ).
DATA(lt_attri) = CAST cl_abap_classdescr( cl_abap_objectdescr=>describe_by_object_ref( lo_app ) )->attributes.
DATA(lt_test) = VALUE abap_attrdescr_tab(
decimals = '0'
visibility = 'U'
is_inherited = ''
is_constant = ''
is_virtual = ''
is_read_only = ''
alias_for = ''
( length = '8' name = 'Z2UI5_IF_APP~ID' type_kind = 'g' is_interface = 'X' is_class = '' )
( length = '2' name = 'CHECK_INITIALIZED' type_kind = 'C' is_interface = '' is_class = '' )
( length = '8' name = 'SV_STATUS' type_kind = 'g' is_interface = '' is_class = 'X' )
( length = '8' name = 'T_TAB' type_kind = 'h' is_interface = '' is_class = 'X' ) ).
IF lt_test <> lt_attri.
cl_abap_unit_assert=>fail( msg = 'utility - get abap_attrdescr_tab table wrong' quit = 5 ).
ENDIF.
ENDMETHOD.
ENDCLASS.
CLASS ltcl_unit_02_app_start DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
DURATION MEDIUM
RISK LEVEL critical.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
DATA product TYPE string.
DATA quantity TYPE string.
DATA check_initialized TYPE abap_bool.
CLASS-DATA sv_state TYPE string.
PROTECTED SECTION.
PRIVATE SECTION.
METHODS test_index_html FOR TESTING RAISING cx_static_check.
METHODS test_xml_view FOR TESTING RAISING cx_static_check.
METHODS test_id FOR TESTING RAISING cx_static_check.
METHODS test_xml_popup FOR TESTING RAISING cx_static_check.
METHODS test_bind_one_way FOR TESTING RAISING cx_static_check.
METHODS test_bind_two_way FOR TESTING RAISING cx_static_check.
METHODS test_message_toast FOR TESTING RAISING cx_static_check.
METHODS test_message_box FOR TESTING RAISING cx_static_check.
METHODS test_timer FOR TESTING RAISING cx_static_check.
METHODS test_landing_page FOR TESTING RAISING cx_static_check.
METHODS test_scroll_cursor FOR TESTING RAISING cx_static_check.
METHODS test_navigate FOR TESTING RAISING cx_static_check.
METHODS test_startup_path FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_02_app_start IMPLEMENTATION.
METHOD test_index_html.
* z2ui5_cl_http_handler=>client = VALUE #( t_header = VALUE #( ( name = '~path' value = 'dummy' ) ) ).
DATA(lv_index_html) = z2ui5_cl_http_handler=>http_get( ).
IF lv_index_html IS INITIAL.
cl_abap_unit_assert=>fail( 'HTTP GET - index html initial' ).
ENDIF.
ENDMETHOD.
METHOD z2ui5_if_app~main.
IF check_initialized = abap_false.
check_initialized = abap_true.
product = 'tomato'.
quantity = '500'.
ENDIF.
CASE client->get( )-event.
WHEN 'BUTTON_POST'.
client->message_toast_display( |{ product } { quantity } - send to the server| ).
WHEN 'BACK'.
client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app_stack ) ).
ENDCASE.
IF sv_state = 'TEST_MESSAGE_BOX'.
client->message_box_display( text = 'test message box' ).
ENDIF.
IF sv_state = 'TEST_MESSAGE_TOAST'.
client->message_toast_display( text = 'test message toast' ).
ENDIF.
CASE sv_state.
WHEN 'TEST_ONE_WAY'.
client->view_display( z2ui5_cl_xml_view=>factory( client )->shell(
)->page( title = 'abap2UI5 - First Example'
navbuttonpress = client->_event( 'BACK' )
shownavbutton = abap_true
)->simple_form( title = 'Form Title' editable = abap_true
)->content( 'form'
)->title( 'Input'
)->label( 'quantity'
)->input( client->_bind( quantity )
)->label( 'product'
)->input( value = product
enabled = abap_false
)->button( text = 'post'
press = client->_event( 'BUTTON_POST' )
)->get_root( )->xml_get( ) ).
WHEN 'TEST_POPUP'.
client->popup_display( z2ui5_cl_xml_view=>factory( client
)->dialog( title = 'abap2UI5 - First Example'
)->simple_form( title = 'Form Title' editable = abap_true
)->content( 'form'
)->title( 'Input'
)->label( 'quantity'
)->input( client->_bind_edit( quantity )
)->label( 'product'
)->input( value = product
enabled = abap_false
)->button( text = 'post'
press = client->_event( 'BUTTON_POST' )
)->get_root( )->xml_get( ) ).
WHEN 'TEST_TIMER'.
client->timer_set( event_finished = 'TIMER_FINISHED'
interval_ms = `500` ).
client->view_display( z2ui5_cl_xml_view=>factory( client )->shell(
)->page( title = 'abap2UI5 - First Example'
navbuttonpress = client->_event( 'BACK' )
shownavbutton = abap_true
)->simple_form( title = 'Form Title' editable = abap_true
)->content( 'form'
)->title( 'Input'
)->label( 'quantity'
)->input( client->_bind( quantity )
)->label( 'product'
)->input( value = product
enabled = abap_false
)->button( text = 'post'
press = client->_event( 'BUTTON_POST' )
)->get_root( )->xml_get( ) ).
WHEN OTHERS.
client->view_display( z2ui5_cl_xml_view=>factory( client )->shell(
)->page( title = 'abap2UI5 - First Example'
navbuttonpress = client->_event( 'BACK' )
shownavbutton = abap_true
)->simple_form( title = 'Form Title' editable = abap_true
)->content( 'form'
)->title( 'Input'
)->label( 'quantity'
)->input( client->_bind_edit( quantity )
)->label( 'product'
)->input( value = product
enabled = abap_false
)->button( text = 'post'
press = client->_event( 'BUTTON_POST' )
)->get_root( )->xml_get( ) ).
ENDCASE.
IF sv_state = 'TEST_SCROLL_CURSOR'.
client->view_display( `test` ).
client->cursor_set( id = 'id_text2' cursorpos = '5' selectionstart = '5' selectionend = '10' ).
client->scroll_position_set( VALUE #( v = '99999'
( n = 'id_page' )
( n = 'id_text3' ) ) ).
ENDIF.
IF sv_state = 'TEST_NAVIGATE'.
DATA(lo_app) = NEW ltcl_unit_02_app_start( ).
sv_state = 'LEAVE_APP'.
client->nav_app_call( lo_app ).
RETURN.
ENDIF.
IF sv_state = 'LEAVE_APP'.
CLEAR sv_state.
client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app ) ).
ENDIF.
ENDMETHOD.
METHOD test_xml_view.
sv_state = ``.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}`
* path_info = 'LTCL_UNIT_02_APP_START'
).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_VIEW->XML->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
<val> = shift_left( <val> ).
IF <val>(9) <> `<mvc:View`.
cl_abap_unit_assert=>fail( msg = 'xml view - intital view wrong' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_id.
sv_state = ``.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}`
* path_info = 'LTCL_UNIT_02_APP_START'
).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `ID->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> IS INITIAL.
cl_abap_unit_assert=>fail( msg = 'id - initial value is initial' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_bind_one_way.
sv_state = `TEST_ONE_WAY`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `OVIEWMODEL->QUANTITY->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `500`.
cl_abap_unit_assert=>fail( msg = 'data binding - initial set oUpdate wrong' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_bind_two_way.
sv_state = ``.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `OVIEWMODEL->OUPDATE->QUANTITY->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `500`.
cl_abap_unit_assert=>fail( msg = 'data binding - initial set oUpdate wrong' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_message_box.
sv_state = `TEST_MESSAGE_BOX`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_MSG_BOX->TEXT->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `test message box`.
cl_abap_unit_assert=>fail( msg = 'message box - text wrong' quit = 5 ).
ENDIF.
UNASSIGN <val>.
lv_assign = `PARAMS->S_MSG_BOX->TYPE->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `information`.
cl_abap_unit_assert=>fail( msg = 'message box - type wrong' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_message_toast.
sv_state = `TEST_MESSAGE_TOAST`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_MSG_TOAST->TEXT->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `test message toast`.
cl_abap_unit_assert=>fail( msg = 'message toast - text wrong' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_timer.
sv_state = `TEST_TIMER`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_TIMER->EVENT_FINISHED->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `TIMER_FINISHED`.
cl_abap_unit_assert=>fail( msg = 'timer - event wrong' quit = 5 ).
ENDIF.
UNASSIGN <val>.
lv_assign = `PARAMS->S_TIMER->INTERVAL_MS->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `500`.
cl_abap_unit_assert=>fail( msg = 'timer - ms wrong' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_xml_popup.
sv_state = `TEST_POPUP`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_POPUP->XML->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
<val> = shift_left( <val> ).
IF <val>(9) <> `<mvc:View`.
cl_abap_unit_assert=>fail( msg = 'xml popup - intital popup wrong' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_landing_page.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : ""}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `PARAMS->S_VIEW->XML->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
<val> = shift_left( <val> ).
IF <val> NS `Step 4`.
cl_abap_unit_assert=>fail( msg = 'landing page - not started when no app' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_scroll_cursor.
sv_state = `TEST_SCROLL_CURSOR`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
ENDMETHOD.
METHOD test_startup_path.
sv_state = `TEST_NAVIGATE`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
ENDMETHOD.
METHOD test_navigate.
sv_state = `TEST_NAVIGATE`.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
ENDMETHOD.
ENDCLASS.
CLASS ltcl_unit_03_app_ajax DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
DATA product TYPE string.
DATA quantity TYPE string.
DATA check_initialized TYPE abap_bool.
CLASS-DATA sv_state TYPE string.
PRIVATE SECTION.
METHODS test_app_change_value FOR TESTING RAISING cx_static_check.
METHODS test_app_event FOR TESTING RAISING cx_static_check.
METHODS test_app_dump FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_03_app_ajax IMPLEMENTATION.
METHOD z2ui5_if_app~main.
IF check_initialized = abap_false.
check_initialized = abap_true.
product = 'tomato'.
quantity = '500'.
ENDIF.
CASE client->get( )-event.
WHEN 'BUTTON_POST'.
client->message_toast_display( |{ product } { quantity } - send to the server| ).
WHEN 'BACK'.
client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app_stack ) ).
ENDCASE.
IF sv_state = 'ERROR'.
z2ui5_lcl_utility=>raise( `exception test` ).
ENDIF.
client->view_display( z2ui5_cl_xml_view=>factory( client )->shell(
)->page( title = 'abap2UI5 - First Example'
navbuttonpress = client->_event( 'BACK' )
shownavbutton = abap_true
)->simple_form( title = 'Form Title' editable = abap_true
)->content( 'form'
)->title( 'Input'
)->label( 'quantity'
)->input( client->_bind( quantity )
)->label( 'product'
)->input( value = product
enabled = abap_false
)->button( text = 'post'
press = client->_event( 'BUTTON_POST' )
)->get_root( )->xml_get( ) ).
ENDMETHOD.
METHOD test_app_change_value.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
DATA(lv_assign) = `ID->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> IS INITIAL.
cl_abap_unit_assert=>fail( msg = 'id - initial value is initial' quit = 5 ).
ENDIF.
DATA(lv_id) = CONV string( <val> ).
DATA(lv_request) = `{"oUpdate":{"QUANTITY":"600"},"ID": "` && lv_id && `" ,"ARGUMENTS":[{"EVENT":"BUTTON_POST","METHOD":"UPDATE"}] }`.
lv_response = z2ui5_cl_http_handler=>http_post(
body = lv_request
).
CLEAR lo_data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
UNASSIGN <val>.
lv_assign = `OVIEWMODEL->OUPDATE->QUANTITY->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> <> `600`.
cl_abap_unit_assert=>fail( msg = 'data binding - frontend updated value wrong after roundtrip' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_app_event.
* DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
* body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_02_APP_START"}}` ).
*
* DATA lo_data TYPE REF TO data.
* /ui2/cl_json=>deserialize( EXPORTING json = lv_response
* CHANGING data = lo_data ).
*
* FIELD-SYMBOLS <val> TYPE any.
*
* UNASSIGN <val>.
* DATA(lv_assign) = `ID->*`.
* ASSIGN lo_data->(lv_assign) TO <val>.
* IF <val> IS INITIAL.
* cl_abap_unit_assert=>fail( msg = 'id - initial value is initial' quit = 5 ).
* ENDIF.
* DATA(lv_id) = CONV string( <val> ).
*
* DATA(lv_request) = `{"oUpdate":{"QUANTITY":"700"},"ID": "` && lv_id && `" ,"ARGUMENTS": [ {"EVENT":"BUTTON_POST","METHOD":"UPDATE"} ] }`.
* lv_response = z2ui5_cl_http_handler=>http_post(
* body = lv_request ).
*
* CLEAR lo_data.
* /ui2/cl_json=>deserialize( EXPORTING json = lv_response
* CHANGING data = lo_data ).
*
* UNASSIGN <val>.
* lv_assign = `PARAMS->S_MSG_TOAST->TEXT->*`.
* ASSIGN lo_data->(lv_assign) TO <val>.
* IF <val> <> `tomato 700 - send to the server`.
* cl_abap_unit_assert=>fail( msg = 'message toast - text wrong' quit = 5 ).
* ENDIF.
ENDMETHOD.
METHOD test_app_dump.
* sv_state = `ERROR`.
* DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
* body = ``
* path_info = 'LTCL_UNIT_03_APP_AJAX' ).
*
* DATA lo_data TYPE REF TO data.
* /ui2/cl_json=>deserialize( EXPORTING json = lv_response
* CHANGING data = lo_data ).
*
* FIELD-SYMBOLS <val> TYPE any.
* UNASSIGN <val>.
* DATA(lv_assign) = `PARAMS->S_VIEW->XML->*`.
* ASSIGN lo_data->(lv_assign) TO <val>.
* <val> = shift_left( <val> ).
* IF <val> NS `MessagePage`.
* cl_abap_unit_assert=>fail( msg = 'system app error - not shown by exception' quit = 5 ).
* ENDIF.
ENDMETHOD.
ENDCLASS.
CLASS ltcl_unit_04_deep_data IMPLEMENTATION.
METHOD z2ui5_if_app~main.
IF check_initialized = abap_false.
check_initialized = abap_true.
t_tab = VALUE #( title = 'Peter'
descr = 'this is a description'
icon = 'sap-icon://account'
( info = 'completed' )
( info = 'incompleted' ) ).
ENDIF.
CASE sv_status.
WHEN `CHANGE`.
client->view_display( z2ui5_cl_xml_view=>factory( client )->shell(
)->page( title = 'abap2UI5 - First Example'
navbuttonpress = client->_event( 'BACK' )
shownavbutton = abap_true
)->list(
" TODO: check spelling: Ouput (typo) -> Output (ABAP cleaner)
headertext = 'List Ouput'
items = client->_bind_edit( t_tab )
mode = `SingleSelectMaster`
selectionchange = client->_event( 'SELCHANGE' )
)->standard_list_item( title = '{TITLE}'
description = '{DESCR}'
icon = '{ICON}'
info = '{INFO}'
press = client->_event( 'TEST' )
type = `Navigation`
selected = `{SELECTED}`
)->get_root( )->xml_get( ) ).
WHEN OTHERS.
client->view_display( z2ui5_cl_xml_view=>factory( client )->shell(
)->page( title = 'abap2UI5 - First Example'
navbuttonpress = client->_event( 'BACK' )
shownavbutton = abap_true
)->list(
" TODO: check spelling: Ouput (typo) -> Output (ABAP cleaner)
headertext = 'List Ouput'
items = client->_bind( t_tab )
mode = `SingleSelectMaster`
selectionchange = client->_event( 'SELCHANGE' )
)->standard_list_item( title = '{TITLE}'
description = '{DESCR}'
icon = '{ICON}'
info = '{INFO}'
press = client->_event( 'TEST' )
type = `Navigation`
selected = `{SELECTED}`
)->get_root( )->xml_get( ) ).
ENDCASE.
ENDMETHOD.
METHOD test_app_deep_data.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_04_DEEP_DATA"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
FIELD-SYMBOLS <tab> TYPE STANDARD TABLE.
FIELD-SYMBOLS <row> TYPE REF TO data.
DATA(lv_assign) = `OVIEWMODEL->T_TAB->*`.
ASSIGN lo_data->(lv_assign) TO <tab>.
ASSIGN <tab>[ 1 ] TO <row>.
DATA ls_tab_test TYPE ty_row.
ls_tab_test = VALUE #( title = 'Peter' info = 'completed' descr = 'this is a description' icon = 'sap-icon://account' ).
lv_assign = `TITLE->*`.
ASSIGN <row>->(lv_assign) TO <val>.
IF <val> <> ls_tab_test-title.
cl_abap_unit_assert=>fail( msg = 'data binding - initial tab data wrong' quit = 5 ).
ENDIF.
lv_assign = `INFO->*`.
ASSIGN <row>->(lv_assign) TO <val>.
IF <val> <> ls_tab_test-info.
cl_abap_unit_assert=>fail( msg = 'data binding - initial tab data wrong' quit = 5 ).
ENDIF.
lv_assign = `DESCR->*`.
ASSIGN <row>->(lv_assign) TO <val>.
IF <val> <> ls_tab_test-descr.
cl_abap_unit_assert=>fail( msg = 'data binding - initial tab data wrong' quit = 5 ).
ENDIF.
ENDMETHOD.
METHOD test_app_deep_data_change.
sv_status = 'CHANGE'.
DATA(lv_response) = z2ui5_cl_http_handler=>http_post(
body = `{ "OLOCATION" : { "SEARCH" : "app_start=LTCL_UNIT_04_DEEP_DATA"}}` ).
DATA lo_data TYPE REF TO data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
FIELD-SYMBOLS <val> TYPE any.
UNASSIGN <val>.
FIELD-SYMBOLS <tab> TYPE STANDARD TABLE.
FIELD-SYMBOLS <row> TYPE REF TO data.
DATA(lv_assign) = `OVIEWMODEL->OUPDATE->T_TAB->*`.
ASSIGN lo_data->(lv_assign) TO <tab>.
ASSIGN <tab>[ 1 ] TO <row>.
DATA ls_tab_test TYPE ty_row.
ls_tab_test = VALUE #( title = 'Peter' info = 'completed' descr = 'this is a description' icon = 'sap-icon://account' ).
lv_assign = `TITLE->*`.
ASSIGN <row>->(lv_assign) TO <val>.
IF <val> <> ls_tab_test-title.
cl_abap_unit_assert=>fail( msg = 'data binding - initial tab data wrong' quit = 5 ).
ENDIF.
lv_assign = `INFO->*`.
ASSIGN <row>->(lv_assign) TO <val>.
IF <val> <> ls_tab_test-info.
cl_abap_unit_assert=>fail( msg = 'data binding - initial tab data wrong' quit = 5 ).
ENDIF.
lv_assign = `DESCR->*`.
ASSIGN <row>->(lv_assign) TO <val>.
IF <val> <> ls_tab_test-descr.
cl_abap_unit_assert=>fail( msg = 'data binding - initial tab data wrong' quit = 5 ).
ENDIF.
UNASSIGN <val>.
lv_assign = `ID->*`.
ASSIGN lo_data->(lv_assign) TO <val>.
IF <val> IS INITIAL.
cl_abap_unit_assert=>fail( msg = 'id - initial value is initial' quit = 5 ).
ENDIF.
DATA(lv_id) = CONV string( <val> ).
DATA(lv_tab) = z2ui5_lcl_utility=>trans_any_2_json( t_tab ).
DATA(lv_request) = `{"oUpdate":{"QUANTITY":"600", "T_TAB":` && lv_tab && `}, "ID": "` && lv_id && `"` && `,"oEvent":{"EVENT":"BUTTON_POST","METHOD":"UPDATE"}}`.
lv_response = z2ui5_cl_http_handler=>http_post(
body = lv_request
).
CLEAR lo_data.
/ui2/cl_json=>deserialize( EXPORTING json = lv_response
CHANGING data = lo_data ).
ENDMETHOD.
ENDCLASS.

File diff suppressed because it is too large Load Diff

View File

@ -1,71 +0,0 @@
CLASS lcl_utility DEFINITION INHERITING FROM cx_no_check.
PUBLIC SECTION.
CLASS-METHODS get_json_boolean
IMPORTING val TYPE any
RETURNING VALUE(result) TYPE string.
CLASS-METHODS check_is_boolean
IMPORTING val TYPE any
RETURNING VALUE(result) TYPE abap_bool.
CLASS-METHODS get_classname_by_ref
IMPORTING in TYPE REF TO object
RETURNING VALUE(result) TYPE string.
CLASS-METHODS get_replace
IMPORTING iv_val TYPE clike
iv_begin TYPE clike
iv_end TYPE clike
iv_replace TYPE clike DEFAULT ''
RETURNING VALUE(result) TYPE string.
CLASS-METHODS get_trim_lower
IMPORTING val TYPE any
RETURNING VALUE(result) TYPE string.
ENDCLASS.
CLASS lcl_utility IMPLEMENTATION.
METHOD get_replace.
result = iv_val.
SPLIT result AT iv_begin INTO DATA(lv_1) DATA(lv_2).
SPLIT lv_2 AT iv_end INTO DATA(lv_dummy) DATA(lv_4).
IF lv_4 IS NOT INITIAL.
result = lv_1 && iv_replace && lv_4.
ENDIF.
ENDMETHOD.
METHOD get_classname_by_ref.
DATA(lv_classname) = cl_abap_classdescr=>get_class_name( in ).
result = substring_after( val = lv_classname sub = `\CLASS=` ).
ENDMETHOD.
METHOD get_json_boolean.
IF check_is_boolean( val ).
result = COND #( WHEN val = abap_true THEN `true` ELSE `false` ).
ELSE.
result = val.
ENDIF.
ENDMETHOD.
METHOD check_is_boolean.
TRY.
DATA(lo_ele) = CAST cl_abap_elemdescr( cl_abap_elemdescr=>describe_by_data( val ) ).
CASE lo_ele->get_relative_name( ).
WHEN `ABAP_BOOL` OR `ABAP_BOOLEAN` OR `XSDBOOLEAN`.
result = abap_true.
ENDCASE.
CATCH cx_root.
ENDTRY.
ENDMETHOD.
METHOD get_trim_lower.
result = CONV #( val ).
result = to_lower( shift_left( shift_right( result ) ) ).
ENDMETHOD.
ENDCLASS.

View File

@ -0,0 +1,23 @@
CLASS ltcl_unit_test DEFINITION FINAL FOR TESTING
DURATION MEDIUM
RISK LEVEL CRITICAL.
PRIVATE SECTION.
METHODS test_create FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_unit_test IMPLEMENTATION.
METHOD test_create.
DATA(lo_view) = z2ui5_cl_xml_view=>factory( ).
DATA(lv_xml) = lo_view->page( `test` )->stringify( ).
IF lv_xml IS INITIAL.
cl_abap_unit_assert=>fail( quit = 5 ).
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@ -10,6 +10,7 @@
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
</asx:values>
</asx:abap>

View File

@ -18,14 +18,13 @@ INTERFACE z2ui5_if_client
TYPES:
BEGIN OF ty_s_config,
controller_name TYPE string,
view_model_edit_name TYPE string,
version TYPE string,
origin TYPE string,
pathname TYPE string,
search TYPE string,
body TYPE string,
END OF ty_S_config.
END OF ty_s_config.
TYPES:
BEGIN OF ty_s_draft,
@ -34,7 +33,7 @@ INTERFACE z2ui5_if_client
id_prev_app TYPE string,
id_prev_app_stack TYPE string,
app TYPE REF TO z2ui5_if_app,
END OF ty_S_draft.
END OF ty_s_draft.
TYPES:
BEGIN OF ty_s_cursor,
@ -51,9 +50,9 @@ INTERFACE z2ui5_if_client
t_scroll_pos TYPE ty_t_name_value,
check_launchpad_active TYPE abap_bool,
check_on_navigated TYPE abap_bool,
s_draft TYPE ty_S_draft,
s_cursor TYPE ty_S_cursor,
s_config TYPE ty_S_config,
s_draft TYPE ty_s_draft,
s_cursor TYPE ty_s_cursor,
s_config TYPE ty_s_config,
END OF ty_s_get.
METHODS view_destroy.