SeleniumHQ / selenium-ide

Open Source record and playback test automation for the web.
https://selenium.dev/selenium-ide/
Apache License 2.0
2.74k stars 740 forks source link

Selenium-side-runner process stops when a command fails #1688

Closed nicolasdonato closed 5 months ago

nicolasdonato commented 11 months ago

💬 Questions and Help

Hello,

I am using selenium-side-runner v4 to be able to interact with html pages. I have weird behavior. My use case, I encapsulated the side-runner library in a nodejs server which allows me to take into account several different calls to interact with html pages. I then use the "run" object found in the TypeScript Run.ts file which allows me to link side-runner to an expressjs type server. However, when a command goes into error (Timeout), the side-runner process stops and does not allow me to be able to return an error and worse, my expressjs server crashes. This induces that if other processes are running, I lose all the work. How can I do to avoid this? I thank you in advance.

Here the logs :

executing type|xpath=//span[@id='inputText']/span/span[2]/input|13400
Unexpected error occured during command: type-xpath=//span[@id='inputText']/span/span[2]/input-13400 retrying...
element not interactable
  (Session info: chrome=111.0.5563.146)
/home/app/node_modules/@seleniumhq/side-runtime/dist/playback-tree/command-node.js:102
            throw new Error(`Operation timed out running command ${this.command.command}:${this.command.target}:${this.command.value}`);
            ^

Error: Operation timed out running command type:xpath=//span[@id='inputText']/span/span[2]/input:13400
    at Timeout._onTimeout (/home/app/node_modules/@seleniumhq/side-runtime/dist/playback-tree/command-node.js:102:19)
    at listOnTimeout (node:internal/timers:569:17)
    at process.processTimers (node:internal/timers:512:7)

Node.js v18.16.0
'RPA server - Selenium Side Runner' in Node.js is listening on port: 3000
nicolasdonato commented 11 months ago

After debug session, it exists strange behavior about this code:

In the file "selenium-webdriver/lib/http.js#execute (L 524)

let response = await client.send(request)

This code has no error returned when a timeout occured. I think, that is provided from file "selenium-webdriver/http/index.js" and "sendRequest" method. So can we will catch the timeout error from webdriver by using this following code ?

request.on('timeout', () => {
  onError(new Error('Timeout of the command --------------------'));
});
toddtarsi commented 11 months ago

@nicolasdonato - Very interesting! Yes, handling all permutations of error emitted from this thing is tricky. If you're looking to do what you're doing and have that level of control, I'd recommend to possibly avoid instrumenting the side-runner, and instead instrument the side-runtime. It's the shared runtime used by both v4 of the IDE and the side-runner. Ultimately, the side-runner is really just a thin wrapper on this as well + some jest and logging, which you clearly already know because you've dove the hell out of the source haha.

toddtarsi commented 11 months ago

But basically, I think all of those jest and CI paradigms are fighting you here, because you're consuming it as a service, when its meant to be a standalone process. Side-runtime is the service both the other things are consuming, and you'll be able to do everything the IDE does with it that way. Please let me know if I can help any further. Sorry to have a kinda convoluted recommendation, but I think you'll fight the tools less that way.

nicolasdonato commented 11 months ago

@toddtarsi I thank you for your answer, so for that I can try to put in place a way to create a sub thread with "setTimeout" methode in javascript otherwise with javascript worker. In my case, side-runner is a good way for the encapsulation for a lot of thing for me :) and I prefered to use it.

So I don't know why the timeout error is not catched by the "request.on('error', ...)" method. It is strange. Do you have an idea on your side for this ? On my side, I tried to put in place a sub process.

toddtarsi commented 11 months ago

@nicolasdonato - This is a dumb question, but when you do it, have you tried something like this:

try {
  const result = await runner.run(xyz)
} catch (e) {
  // handle our error
}

or

   runner.run(xyz).catch(e => {}).then(result => {})
nicolasdonato commented 11 months ago

@toddtarsi I do like that and I see a difference with your version...

Promise.resolve(runner({ // create the runner process for selenium-side-runner with the configuration
     configuration: configuration,
     logger: console
} as HoistedThings).project(payload)) // launch the selenium-side-runner processus
.then(() => {

}).catch((err) => {

});
toddtarsi commented 11 months ago

LGTM! 👍 Lemme know if it works for ya!

nicolasdonato commented 11 months ago

@toddtarsi I have the same issue with your version

toddtarsi commented 11 months ago

@nicolasdonato - Rats! Okay, so something in the error handling isn't working. This surprises me, because when we handle this error from the IDE and the side runner, we have this error all the time and we propagate it to the UX and move on to the next test and stuff.

nicolasdonato commented 11 months ago

Ah ? Yeah it is very strange... It seems in some cases, the Timeout error breaks the current process

nicolasdonato commented 11 months ago

@toddtarsi It is very strange, because, I encapsulate all my code which called side-runner in a sub-process worker and now I can catch the Timeout error. I did not know why I have these 2 behaviors...

toddtarsi commented 11 months ago

It has to be an issue in how the side-runner propagates errors. It's gotta be messing up the passthrough, because I didn't really design it right to function as a service

toddtarsi commented 11 months ago

Sorry about that, but I'm glad you've got a workaround. Sub process for the side runner seems like a much more fitting use pattern thingy anyway.

nicolasdonato commented 11 months ago

Yes indeed, the subprocess is a good way, but I have the other issue which is if a test suite is failed like that, the next test suites will not played.

toddtarsi commented 5 months ago

@nicolasdonato - This is ridiculously far later, but this issue is resolved in latest. Yeah, there was an error emitted by a setTimeout call that broke the playPromise thing. It's fixed now.

github-actions[bot] commented 4 months ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.