2

Is there a way in Robot Framework to run a javascript method that returns a promise and resolve that promise so I could get a result from it? I tried to achieve it in two ways. The first way was to run the Execute Javascript keyword and pass the function, then set wait for some time (with Sleep) and trying to resolve the promise (it already finished to execute in the browser).

The code I used looks like that:

${promise}= Execute Javascript  return runAllTests();
Sleep   30sec   
${result}=  Set Variable    return ${promise}.then(function(result) { return result; });

The result I got with this was just the promise object (I think)

{u'all': {}, u'_setSettlePromisesQueued': {}, u'_setBoundTo': {}, u'_settlePromiseAtPostResolution': {}, u'_isRejectionUnhandled': {}...

I do not paste it all because it's 3000+ characters long, but it's not what I expected for sure. Actually, the result is exactly the same no matter if I put there Sleep keyword or not.

The second way was to use Execute Async Javascript keyword (with modified timeout) and then trying to resolve it.

Set Selenium Timeout    30sec
${result}=    Execute Async Javascript    return runAllTests().then(function(result) { return result});

The function finished to execute in the browser window, but Robot seems not to care and after 30 seconds it reports TimeoutException with this message:

TimeoutException: Message: asynchronous script timeout: result was not received in 30 seconds

I tried to find another way, maybe some built-in mechanism to handle the promises, but I did not find anything like that. Is there any way to do that? I use Robot with Selenium2Library.

Mateusz Cisek
  • 775
  • 11
  • 22

2 Answers2

0

The solution for this is basically in the Selenium2Library documentation. All it takes to make it work is to use the callback function, for example:

Set Selenium Timeout    60sec
${result}=    Execute Async Javascript
...    var callback = arguments[arguments.length-1];
...    runAllTests().then(function() { callback(1); }).catch(function() { callback(0); });

This will set the result to 1 or 0 (as a string, not integer), depending on what is returned by this function (resolved or rejected promise). I was confused by this callback used in this example but it's working.

Mateusz Cisek
  • 775
  • 11
  • 22
0

Following keyword allows getting back the promise response or error message.

PS Execute Async Promise
    [Arguments]    ${promise}    ${timeout}=${PS_MAX_WAIT}    ${return_function}=${None}    ${failure_marker}=UNEXPECTED_STATE
    [Documentation]    Wrapper calling a asynchronous JavaScript ${promise} and wait till max ${timeout}, if it's promise returns \ a success or failure.
    ...
    ...    Failure case:
    ...    - \ the error.message is catched and reported
    ...
    ...    Success case:
    ...    - When ${return_function} is None, the promise response will be returned directly (default)
    ...    - Otherwise, an additional *then* chain step is added to modify / prepare promise response .
    ...
    ...    Sample: If ${return_function} is _JSON.stringify(response)_ , a chain step _then( function(response) { return JSON.stringify(response); } )_ is added
    [Tags]    internal
    Set Selenium Timeout    ${timeout}
    ${promise_chain}=    Set Variable If    '${return_function}'!='${None}'    ${promise}.then( function(response) { return ${return_function}; } )    ${promise}
    ${error_return}=    Set Variable    '${failure_marker} - ' + error.name + ' - ' + error.message
    ${result}=    Execute Async Javascript    var callback = arguments[arguments.length-1];    ${promise_chain}.then(function(response) { callback( response ); }).catch(function(error) { callback( ${error_return} ); });
    Should Not Contain    ${result}    ${failure_marker}    js call aborts with ${result} - ${promise_chain}
    [Teardown]    PS Set Delay and Timeout to Default
    [Return]    ${result}

Sample robot suite using this keyword see robot-framework_sample_promises.robot.

It interacts with sample page Promises tests, provided by JavaScript Promises: an Introduction

lczub
  • 31
  • 3
  • Thanks, but it was a while ago, I don't work with Robot Framework anymore and I won't be able to check this solution in the nearest future :) But thanks anyways :) – Mateusz Cisek Jan 03 '20 at 23:18