8

I am using Nightwatch to test that the correct value has been given to a div within an iframe.

My html;

<div class="o-ads__inner" id="leaderboard-gpt">
  <div id="google_ads_iframe">
    <iframe id="some_id">
      #document
        <html>
          <head></head>
          <body>
            <div id="ad-data" creative-id="53134803289">
              <!-- All of the stuff -->
            </div>
          </body>
        </html>
    </iframe>
  </div>
  <iframe><!-- Another iframe (I don't want) --></iframe>
</div>

This is my nightwatch test;

module.exports = {
  'Leaderboard Visibility' : function (client) {
    client
    .url(some_url)
    .waitForElementVisible('body', 5000)
    .waitForElementPresent('#leaderboard > iframe', 10000)
    .pause(5000)
    .frame(0)
      .pause(5000)
      .waitForElementPresent('div#ad-data', 5000)
      .assert.attributeContains('div#ad-data', 'creative-id', '53134803289')
    .end();
  }
};

The error I get from Nightwatch is Timed out while waiting for element <div#ad-data> to be present for 5000 milliseconds. I know that it is there by checking before the failing line.

I have put in the 2 .pause(5000)s as similar questions suggest it may be a problem that the contents in the iframe isn't loading quickly enough. I don't think that's the case here due to some debugging I have done but I have left them there for the time being.

I'm thinking that I can't access the div#ad-data because the iframe has it's own contentDocument property, which contains the head & body (and thus subsequent divs).

How can I assert the value of the div's property within the iframe's contentDocument using Nightwatch?

Simon Legg
  • 683
  • 7
  • 20
  • how did you get the frame without the id.. iframe will not have same id everytime ? – Jaimin Aug 02 '16 at 15:51
  • @Jaimin my iframe's id wasn't set by me, we didn't know what it was because it was being served by an ad server. But we generally knew that it was the first iFrame on the page. – Simon Legg Aug 05 '16 at 10:02
  • Thanks for info. I am checking that google ad is getting rendered or not using nightwatch. Have found some ways. – Jaimin Aug 05 '16 at 15:08
  • @Jaimin cool, if you have success, I would love to see how you do it. – Simon Legg Aug 07 '16 at 21:49
  • checkout this test case, https://github.com/prebid/Prebid.js/blob/master/test/spec/e2e/testcase1/dom-group/dom_spec.js – Jaimin Sep 23 '16 at 19:56
  • i know this ticket is three years old as at 2019, but i still think pausing a test is causing trouble for your test runners. given that you have a 5 second pause, imagine the time it would cost you to run the test in development, integration and UAT, pausing tests just causes too much overhead for no apparent reason – Waweru Mwaura Jan 09 '19 at 08:32

2 Answers2

8

for your first iframe <iframe id="some_id"> use .frame('some_id').

Killuminati
  • 261
  • 2
  • 11
  • Thanks, I didn't actually mean to put an id on the iframe in the code above, it does have one but it potentially changes depending on which ad gets inserted which is why I was doing `.frame(0)`. That being said when I was trying with the id (which will be correct every now and then) I was doing `.frame('#some_id')` to select it and kept missing the fact I'd put a `#` in it. – Simon Legg Jan 05 '16 at 09:59
  • 1
    And then to escape the iframe, `.frameParent()` – Matt S Dec 15 '16 at 02:17
7

Dynamic id external iframe access

Here is a way around to test solve this issue, get the attribute id and use it in the frame, frame(0) does not provide access, nightwatch need iframe id. and for dynamic generated id's here is what you can do.

module.exports = {
      'Checkout Braintree' : function (client) {
        client
        .url('#enter_your_url_here')
        .waitForElementPresent('[data-e2e="brainTree3Ds"]', 10000)
        .pause(5000)
        .perform(() => {
          client.getAttribute('[data-e2e="brainTree3Ds"] iframe', 'id',(result) => {
            client
              .frame(result.value)
              .setValue('input[name="external.field.password"]', 1234)
              .click('input[type="submit"]');
          });
        })
        .testSuccessPage() // External Command
        .end();
    }
Community
  • 1
  • 1
Tarandeep Singh
  • 1,322
  • 16
  • 16
  • Hi Tarandeep. good answer but I'm getting an error saying `Error while running .clickElement() protocol action: unknown error: cannot determine loading status` referring to the `.click('input[type="submit"]');` part. do you know why that would be? – Red Baron May 28 '20 at 11:52