4

Our webdriver test needs to hide an element that is getting recorded multiple times in screenshots as the browser scrolls down the page. It is a floating element.

I have:

 it('should save Food blog page screenshotsscreenshots', async () => {
    const adjustedURL = new browser();
    await adjustedURL
      .url('en-au/blog/elements-and-templates-food-sustainability/')
      .execute(() => {document.getElementByID("_hjSafeContext_7335155").style["opacity"] = "0";})
      .pause(4000)
      .saveFullPageScreen('AU-Food-blog', {});
  });

but receive an error TypeError: browser is not a constructor.

If I use:

  it('should save Food blog page screenshotsscreenshots', async () => {
    await browser
      .url('en-au/blog/elements-and-templates-food-sustainability/')
      .execute(() => {document.getElementByID("_hjSafeContext_7335155").style["opacity"] = "0";})
      .pause(4000)
      .saveFullPageScreen('AU-Food-blog', {});
  });

I get browser.url(...).execute is not a function

Edit2, perhaps the Intercom HTML changed, and I now need to target .intercom-lightweight-app:

  it('should save Food blog page', async () => {
    await browser.url('en-au/blog/elements-and-templates-food-sustainability/');
    await browser.pause(7000)
    await browser.execute(() => {document.querySelector(".intercom-lightweight-app").style.display = "none";});
    await browser.execute(() => {document.querySelector(".intercom-lightweight-app").style.position = "relative";});
    await browser.saveFullPageScreen('AU-Food-blog', {});
  });

If I set the opacity of .intercom-lightweight-app-launcher to 0 manually, the Intercom widget becomes invisible, but the above changes to the webdriver code mean the Intercom widget is still baked into the screenshot.

Steve
  • 2,066
  • 13
  • 60
  • 115
  • 3
    FYI not overly related but `document.getElementsByID()` should be `document.getElementById()`. – Zze Mar 07 '23 at 05:14
  • 1
    `document.getElementByClass` is not a function, but you can use [`document.querySelector`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) or [`document.getElementsByClassName(...)[0]`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName). I've updated my answer. – Steve Mar 09 '23 at 12:13
  • What I would try is set the user agent via WebDriver and use that in the code to programmatically switch off Intercom. Depending on which bundler you use, you could make it so that this kind of runtime check are automatically removed from the production bundle. Probably a bad idea, but worth a shot? – customcommander Mar 10 '23 at 11:18

1 Answers1

1

It doesn't look like you can chain browser methods with WebdriverIO. Instead you can reuse the browser object, and await each method, like so:

  it('should save Food blog page screenshots', async () => {
    await browser.url('en-au/blog/elements-and-templates-food-sustainability/');
    // intercom might be loaded with different class names, we want to select all of them
    var intercom = await browser.$('.intercom-app, .intercom-lightweight-app');
    // waits up to 30 seconds for the element to be added to DOM
    await intercom.waitForExist({ timeout: 30000 });
    await browser.execute(() => {document.querySelector(".intercom-app, .intercom-lightweight-app").style.opacity = "0";});
    await browser.pause(4000);
    await browser.saveFullPageScreen('AU-Food-blog', {});
    // some test here
  });
Steve
  • 10,435
  • 15
  • 21
  • Thanks, I was using the same structure of code originally, but this never worked. I've made an edit to the question. – Steve Mar 09 '23 at 04:00
  • The intercom widget is still not being hidden by this execute command. The classname is correct and setting opacity to 0 for a new `.intercom-lightweight-app-launcher` rule manually hides the widget. – Steve Mar 13 '23 at 22:30
  • @Steve, does moving the `await browser.pause()` call to above the `await browser.execute()` call do anything? It might be an issue where intercom takes a while to load. – Steve Mar 14 '23 at 12:31
  • I've added an **Edit2** to the question – Steve Mar 15 '23 at 05:27
  • I've made that change, the Intercom widget hides after 7s, then the .pause ends, the intercom widget reappears in expanded form, and the console gives javascript error: javascript error: Cannot read properties of null (reading 'style') – Steve Mar 15 '23 at 05:43
  • Intercom is delivered by Segment, which is loaded by NextJS @ `mandoemedia.com`. If I can disable Segment, the Intercom widget won't load. There is a ` – Steve Mar 15 '23 at 06:25
  • I think the solution you have would work for a normal HTML element. – Steve Mar 15 '23 at 06:35
  • You may have more luck with [`waitForExist`](https://webdriver.io/docs/api/element/waitForExist) (see my edited answer), though it really is hard to diagnose without an actual web page – Steve Mar 15 '23 at 11:54
  • The website is `mandoemedia.com` – Steve Mar 16 '23 at 02:05
  • `waitForExist` did not work – Steve Mar 16 '23 at 02:07
  • @Steve, When I use web inspector and refresh a few times it looks like the overall intercom element is inconsistently loaded with different classes, sometimes as `.intercom-lightweight-app`, sometimes as `.intercom-app`, though it might be different for webdriverio, depending on configuration. For multiple scenarios, you'd want a query selector that selects any of those classes, like `'.intercom-lightweight-app, .intercom-app`. I've updated my answer. – Steve Mar 16 '23 at 15:05
  • That hides Intercom, then the browser scrolls and the Intercom widget reappears, both in default small form, and also extended form (out to the left). The same JS error occurs in webdriver: `javascript error: javascript error: Cannot read properties of null (reading 'style')` – Steve Mar 17 '23 at 00:28