0

I have a very simple requirement to load a web page, wait until it's finished loading, and then wait for an element to become present/visible (this only happens after the page has signaled that it finished loading) before doing anything else with the page.

I tried using the WebBrowser control, but struggled with finding a way to wait for the element.

I looked at using CefSharp but I was told the only way is to inject js, which I'm not all that keen on doing.

I also looked at Selenium WebDriver too and the WebDriverWait appears to do exactly what I want, but the fact that it's not actually a control, cannot be hidden and requires browsers to be installed is a no-no for me.

Is there a way of doing this which does not involve using Thread.Sleep in either WebBrowser, CefSharp or any other project I haven't mentioned yet?

EDIT: Some extra information...

I am using this for web automation. In this particular instance to login to a website (I'm not storing passwords, don't worry).

The particular website in question supports different authentication methods at a user level, so after entering the username it runs a js script which determines whether to then ask for the password or for something like phone auth, smartcard auth, etc. The js script does not fire the DocumentCompleted event, which is what I'm struggling with at the moment.

The idea is that if it asks for smartcard or phone auth to keep the form/control with .Visible = false the whole time and just show it if the user is set for username/password auth.

So depending on what happens after I automate entering the username, it will either ask for a password, smartcard or phone auth and I need to wait for the DOM to change so that one of those 3 elements becomes visible so I know what to do.

I dislike Selenium because it involves the user having to install browsers, it's hard/impossible to make it hidden, it's not an actual control I can drop on my form, etc etc.

JohnUbuntu
  • 699
  • 6
  • 19
  • WebBrowser.DocumentCompleted() is fired when the document is finished loading. – Mathemats Jan 31 '16 at 23:16
  • @Mathemats the DOM element only appears after that event is fired, I tried that already. – JohnUbuntu Jan 31 '16 at 23:22
  • This is surely just JavaScript, but I'm confused by some of the language. When you say "I have a very simple requirement" - is this meant to be manual, occasional job, or a test scenario, or just a standard web dev thing where one element triggers another to do something? In which JQuery (or just standard JS) will cover all of it. E.g. https://developer.mozilla.org/en-US/docs/Web/Events/load. Even if your elem loads dynamically, you can just add a listener to that? – Andrew Regan Jan 31 '16 at 23:25
  • Your requirement is unclear. are you trying to load a web page within an Iframe? – Sam Jan 31 '16 at 23:37
  • Could you answer these question to confirm my understanding? 1. Do you use CefSharp to embed chromium into your application? 2. Are trying to open a web page on your application then check if the given element exists? 3. Does Selenium get the correct window (check webdriver.Title)? – Buaban Feb 01 '16 at 02:55
  • You can use `WebDriver/Selenium` with `CefSharp`, see https://bitbucket.org/chromiumembedded/cef/wiki/UsingChromeDriver.md for a guide on how to use it with `CEF` (`CefSharp` is just a wrapper really) – amaitland Feb 01 '16 at 08:31
  • Otherwise as you've already been suggested javascript is the key (At least in the context of `CefSharp`). – amaitland Feb 01 '16 at 08:31
  • @Buaban 1. I am actually trying to do everything using the WebBrowser control, but have no problems with using CefSharp if that becomes easier. 2. Yes, with one small correction: **wait** until it exists (which happens after `DocumentCompleted` is fired). 3. I haven't tried Selenium on this project, I created a new one just to see what it was capable of and while I love the `WebDriverWait` the rest of Selenium doesn't quite fit my project. See my updated question for a better understanding. – JohnUbuntu Feb 01 '16 at 11:59
  • JS is really the way, whether you have to listen for events, wait a while, poll etc. and no additional components to install. Does this sound a good fit? http://stackoverflow.com/q/20487472/954442, or else https://developer.mozilla.org/en/docs/Web/API/MutationObserver (needs recent browsers) – Andrew Regan Feb 01 '16 at 12:28
  • @JohnUbuntu, see if [this](http://stackoverflow.com/a/20934538/1768303) helps. – noseratio Feb 01 '16 at 12:49
  • @amaitland can you provide some example of how to do this using js in CefSharp? – JohnUbuntu Feb 01 '16 at 16:14
  • here's an example: https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Example/ScriptedMethods.cs#L105 This is the C# bound object with the RaiseEvent method that the JS invokes. https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Example/ScriptedMethodsBoundObject.cs you can dig through the example projects to see most of the features demonstrated. – amaitland Feb 01 '16 at 22:16

1 Answers1

1

I know this is pretty old, but I figured I would add an answer in case anyone runs into it as well.

I have a similar setup to you that requires authentication prior to running each test, so prior to moving on with a test I will wait for elements to load (without checking the DocumentCompleted() method).

What I do is use a helper that takes in some condition, in my case it's Func<bool>, then checks for this condition every time period x, until a timeout of y. Both X and Y are configurable, but they have a default of say 1 second and 10 seconds. You can make the implementation decision on whether or not to suppress exceptions inside the method, but I would recommend doing it so that ElementNotFound exceptions do not stop the execution.

The timing helper function definition note: time in milli-seconds.

public static bool WaitFor(Func<bool> condition, int timeout = 10000, int waitTimePeriod = 1000)

Examples of use would be:

  • Waiting for an element on the page to finish loading (if the component has a loading indicator)
  • Waiting for an element to appear in the DOM
  • Waiting for an element to be removed from the DOM
CJLee
  • 21
  • 3