zefoy / ngx-perfect-scrollbar

Angular wrapper library for the Perfect Scrollbar
MIT License
521 stars 116 forks source link

Protractor not working with element not visible without scrolling into it #255

Open micobarac opened 5 years ago

micobarac commented 5 years ago

Protractor cannot find element not visible initially, without scrolling into it.

Protractor throws this error:

- Failed: element not interactable
    (Session info: chrome=75.0.3770.142)
    (Driver info: chromedriver=75.0.3770.90 (a6dcaf7e3ec6f70a194cc25e8149475c6590e025-refs/branch-heads/3770@{#1003}),platform=Mac OS X 10.14.6 x86_64)

If I remove perfect scrollbar and let the native one do it's job, everything works just fine.

sconix commented 5 years ago

We have had no issues with protractor in our app so I would look into your styles etc. for the cause.

micobarac commented 5 years ago

I have a very lengthy sidenav, and protractor seems unable to reach items that are out of visible area.

Do you use some focusing technique, to activate scrollbar in your protractor tasks?

sconix commented 5 years ago

Should have read bit more carefully, I understood that scroll area not visible before scrolling. Anyway we did have tests that scrolled the scroll area, but unfortunately not anymore since we have already switched to Cypress.

Anyway I think you should be able to get the directive reference and just call scrollToBottom for example.

micobarac commented 5 years ago

Invoking this method:

scrollToElement(qs, offset?, speed?)   // Animate scroll to element matching query selectors.

looks like the only option, but I cannot make it work :(.

micobarac commented 5 years ago
  getSidebarItem(route: string): ElementFinder {
    this.scrollToSidebarItem(route);
    return element(by.xpath(`//op-sidebar-section//div[contains(@class,'item')][@ng-reflect-router-link='${route}']`));
  }

  getSidebarScrollbar(): ElementFinder {
    return element(by.xpath(`//perfect-scrollbar[@class='sidebar-scrollbar']`));
  }

  scrollToSidebarItem(route: string) {
    browser.executeScript(
      `arguments[0].scrollToElement('[ng-reflect-router-link]="${route}"')`,
      this.getSidebarScrollbar()
    );
  }

This throws the error Failed: javascript error: arguments[0].scrollToElement is not a function.

How to I access the native scrollbar instance with protractor?

micobarac commented 5 years ago

I've made a workaround by using the browser's native scrollIntoView method:

  getSidebarItem(route: string): ElementFinder {
    const item = element(
      by.xpath(`//op-sidebar-section//div[contains(@class,'item')][@ng-reflect-router-link='${route}']`)
    );
    this.scrollToSidebarItem(item);
    return item;
  }

  scrollToSidebarItem(item: ElementFinder) {
    browser.executeScript(`arguments[0].scrollIntoView()`, item);
  }

Nevertheless, a big question still remains: How to use protractor with perfect scrollbar by using component's scroll methods???

sconix commented 5 years ago

Its more of a general Angular question how to access element references from Protractor tests. Since you are getting the DOM element and not the Angular reference which has the API for scrolling to bottom etc.