I regularly have the problem when testing with selenium that the built-in waits are not enough, have spent a lot of time looking in to why, and there are a few ways to try to address that and make the tests stable. But first, let me point out, waiting for an element to be clickable
with Selenium is the strongest condition one can use, in other words it will induce the longest wait from any EC.
All the function even does, from the docs, is wait for the element to be visible
and enabled
. (If you look at the source code you can see, I think I recall correctly, that visible
means the element does not have attribute value='hidden'
, and enabled
means it does not have any attribute called disabled
.) Anyway, all this to say that your line
wait.until(ExpectedConditions.elementToBeClickable(element));
has already checked for visibility, so the line that follows it is redundant.
Now to your actual question. I approach the a problem like this usually one of the following ways. The main thought is to figure out what you actually need to wait for before proceeding with your test, and, obviously, wait appropriately.
Since it is throwing ElementNotInteractableException, I think you must try and find out what is actually going on in the app when this happens. Try taking screenshots at this step, and/or logging all or part of the page source to figure out: what is different between runs where your code works, and where it fails? Is there an element covering up your target? If so, maybe you can execute some javascript to get rid of that element. Or, you could wait for that element to NOT be visible. Or, you may find some other condition in the page source that you can wait for to account for this apparent edge case in your tests.
If above doesn't work, Look at the network traffic in your app, again looking for differences between when the test passes and fails. Maybe there is something you can wait for; some request to be made or completed with some status?
If above doesn't work, I start to get to "throw in the towel" stage. See if there is any reasonably short hard-coded wait that, perhaps in combination with other techniques, makes your test pass reliably.
If above doesn't work, implement retry logic, ostensibly for just this single test or failure, to reduce the chance of it impacting your whole run
Finally, if I cannot get any of that to work, the test is intolerably flaky, and it NEEDS to be run, just run the test manually. Some workflows are nearly or actually impossible to automate with Selenium, and at a certain point the effort spent writing and maintaining the code exceeds that which would be required to run the test manually. You also have to accept that some flakiness is inherent with a large amount of Selenium tests running (for most apps anyway), but of course that shouldn't stop your apparently diligent efforts to write the most reliable tests possible.