1

After reading Dianyang Wu article and this excellent post I managed to build a small .net app (almost a C&P from Wu source code) to automatize tests (let's call it protoTestApp). My final goal is to open a dozen small windows and in each simulate a different user interacting with a web app to stress it.

It works for some extend but after I logon on the web app (let's call it InternalTestSubject) it calls a external url (let's call it ExternalTestSubject) and injects it's content on a iFrame. This particular external url is another web app and it ill look up for the parent window to get some parameters. Opening ExternalTestSubject directly is not a option.

My problem is at my protoTestApp I want to also interact with that ExternalTestSubject (find a button by id, click it, etc) but at my CompletedEvent handler the iFrame is still empty.

The WebBrowser shows both web apps full loaded and working, so I suppose the handler is just not waiting for the iFrame content to load since it's done by a Ajax async call.

Any advice to acomplish it?

Community
  • 1
  • 1
jean
  • 4,159
  • 4
  • 31
  • 52
  • How's action to fill iFrame initiated? is it some JavaScript that triggers by onload event that does AJAX call an injects response into an iFrame? – LB2 May 14 '14 at 21:22
  • InternalTestSubject is a .net MVC webapplication. the iFrame is dynamically generated by the bundled index.js at the ready event and appended to a div declared at the index.cshtml. the iFrame points to ExternalTestSubject URL. So far, my WebBrowserDocumentCompletedEventHandler is called twice (after being called first time by the logon page) and in both I can see the empty iFrame, I suppose the handler is not waiting for the iFrame document to load – jean May 15 '14 at 11:20
  • _"I can see the empty iFrame"_ as in visually, or when trying to access it's windows properties / DOM? Where I'm going with this is I'm wondering if you're running into same-origin policy restrictions as it pertains to iFrames. – LB2 May 15 '14 at 14:56
  • I can visually see the iFrame full loaded into the browser but at the event the iFrame is empty. No restriction since both apps are hosted at the same domain (It's a working in production solution) – jean May 19 '14 at 11:19

2 Answers2

1

I think I explained this in the answer you linked (and in more details in another related answer). AJAX pages are non-determinustic, so there is no generic approach.

Use periodic asynchronous polling to watch the page's current HTML snapshot or DOM for changes, the linked post illustrates how to do that. You can poll the frame's content in the same way.

Community
  • 1
  • 1
noseratio
  • 59,932
  • 34
  • 208
  • 486
  • Before posting this question I played a bit with the source code you let at github (nice piece of code btw). Using your console solution gives me same results: A empty iFrame. Btw at the WebBrowserDocumentCompletedEventHandler isBusy is always false and I must to figure out how to use something like that task/wait in a no console solution – jean May 15 '14 at 11:22
  • @jean, what I meant is that after simulating the click you need to keep polling the DOM content of `iframe` using the `Task.Delay` technique as in that code (or a timer), in case `WebBrowserDocumentCompletedEventHandler` doesn't give you what you're after. – noseratio May 15 '14 at 11:26
  • Shame, no surprise I failed. Now I see I understand your code even less I guessed. Ill try harder next time. Maybe I can manage to put that github project to work with this scenario – jean May 15 '14 at 11:36
  • @jeans, hmm... is it because of `async/await` it's hard to understand? I think it'd probably be more confusing if I used a pyramid of callbacks instead. – noseratio May 15 '14 at 11:49
  • I suppose it's because I'm used to callbacks pyramids and is my first time writing console/task and I need to digest some things. As I said at first comment it gives me the same result (a empty iFrame) but I ill try to debug this a little harder next time. There's really no way the WebBrowserDocumentCompleted handler can be used? I tried to create & attach one of those to the iFrame itself but does not worked even if the WebBrowser fully loaded the app. – jean May 15 '14 at 14:02
  • @jean, I can't tell what exactly is going on there. But it's quite possible that the page inside the frame starts some AJAX activity upon `window.onload` or jQuery's `ready` event. At that time, `DocumentCompleted` has already been fired for the empty frame's document (which initially contained only static JavaScript). – noseratio May 15 '14 at 14:08
  • I agree, that's exact the scenario. Both apps consumes web services *via* ajax – jean May 19 '14 at 11:30
  • @jean, the DOM polling is the best you could do then. – noseratio May 19 '14 at 16:17
0

I can imagine the frame reports to be ready but it actually does not. For instance, the frame contains frames, you have no way to know whether all these frames are loaded by using DocumentCompleted event.

In short: Using a frame to load external stuff and do the testing is not a good approach. Even if you use a timer to check the loading status manually. But according to security considerations, you will have many problems to access the DOM.

I have two suggestions for you:

  1. Create a WebBrowser instance and open external test subject into it. You will have a very good chance to know, whether document (and its frames) have been loaded completely. You still have the full control to access any elements of the WebBrowser or cookies or click elements or change elements.

  2. Use 3rd tool such as Selenium as test driver.


Update 1:

As the questioner does not want any 3rd tool, I'd suggest let the internal test subject query the loading completeness of the target frame periodically. Possible code can be check document.readyState == 'complete'.

So far as I know, as the external test subject is embedded as frame, due to security consideration, you might not able to access the DOM of the frame. In other words, you cannot do mouse clicks, etc., unless you change the security settings for the Webbrowser control first.

stanleyxu2005
  • 8,081
  • 14
  • 59
  • 94
  • The question stated opening the external test subject is not a option since it ill not work properly out of the internal test subject. Think both as an aquarium and a fish. Also tried to do it dynamically, finding the iFrame and "attaching" it to a new WebBrowser and not worked (the created instance does not fire the events). Buying a third party tool is not a option here. – jean May 19 '14 at 11:24
  • @jean I've put an update, please check. But I doubt the approach will not work. BTW: Selenium is free. – stanleyxu2005 May 19 '14 at 12:31