1

My objective is to open a webpage, and click the app button for a specific app, like Anaplan. In the past, I've used get element by CSS selector with the combination of class, and ID, as shown in this past post.

first_item = driver.find_element_by_id("anaplan")

I've come across a webpage where the buttons seem to have literally no ID whatsoever, or unique values:

enter image description here

enter image description here

HTML output of the Anaplan App button:

<a
  aria-label="launch app Anaplan"
  class="chiclet a--no-decoration"
  data-se="app-card"
  href="https://gartner.okta.com/home/anaplan/0oaforg08lyATdLuw4x6/2487"
  draggable="true"
  ><article class="chiclet--article">
    <button
      class="chiclet--action"
      tabindex="0"
      aria-label="Settings for Anaplan"
      data-se="app-card-settings-button"
    >
      <svg
        class="chiclet--action-kebab"
        width="20"
        height="4"
        viewBox="0 0 20 4"
        fill="#B7BCC0"
        xmlns="http://www.w3.org/2000/svg"
      >
        <circle cx="2" cy="2" r="2"></circle>
        <circle cx="10" cy="2" r="2"></circle>
        <circle cx="18" cy="2" r="2"></circle>
      </svg>
    </button>
    <section class="chiclet--main" data-se="app-card-main">
      <img
        class="chiclet--main-logo"
        src="https://ok11static.oktacdn.com/fs/bcg/4/gfs1ev15ab63zqgZ91d8"
        alt="Anaplan logo"
      />
    </section>
    <footer class="chiclet--footer" data-se="app-card-footer">
      <o-tooltip content="Anaplan" position="bottom" class="hydrated"
        ><div slot="content"></div>
        <div aria-describedby="o-tooltip-0">
          <h1 class="chiclet--app-title" data-se="app-card-title">Anaplan</h1>
        </div>
      </o-tooltip>
    </footer>
  </article>
</a>

I grabbed the Xpath of the Anaplan button, which shows the following:

/html[@class='hydrated wf-proximanova-n4-inactive wf-
inactive']/body[@class='default']/div[@id='root']
/div[@class='enduser-app ']/section[@class='content-frame']
/main[@class='main-container has-top-bar']/div[@class='dashboard--main']/section[@id='main- 
content']/section[@class='chiclet-area']
/section[@class='chiclet-grid--container']
/section/section[@class='chiclet-grid section-appear-done section-enter-done']
/a[@class='chiclet a--no-decoration'][1]/article[@class='chiclet--article']

The only differences between apps is the number in the bracket: /a[@class='chiclet a--no-decoration'][1], where 1 seems to be Anaplan, 3 is G Drive, and so on. Is there a way to select elements such as this where there appears to be no unique identifier at all?

user18139
  • 188
  • 1
  • 3
  • 13

2 Answers2

1

It is possible both with xpath and css. Example of xpath:

Anaplan:

//a[contains(@aria-label, 'Anaplan')]/article/button

Or:

//button[contains(@aria-label, 'Settings for Anaplan')]

Spam Quarantine:

//a[contains(@aria-label, 'Spam Quarantine')]

G-suite

//a[contains(@aria-label, 'G Suite Drive')]

The main idea is that you can find an element by writing a partial name of an attribute.

Update:

If an element is located inside an iframe, you should wait for it to load and switch to it. Selenium has very convenient method for it: frame_to_be_available_and_switch_to_it

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.get(url)
wait = WebDriverWait(driver, 15)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[data-testid=shell-content]")))

After switching to iframe you work with elements inside it.

vitaliis
  • 4,082
  • 5
  • 18
  • 40
  • All of these worked. But don't seem to work on an iframe either, similar to the other solutions. Is an iframe different somehow? pastebin.com/D5Fzn6hu – user18139 May 04 '21 at 17:01
1

To locate the first button you can use one of the following xpaths //a[@aria-label='launch app Anaplan'] or //a[contains(@href,'anaplan')] and there are many other unique combinations. The same can be done with css selectors
Similarly to the above there are several combinations for all the other navigation buttons you provided here.
In case the element located inside <iframe> you have to switch to that <iframe> first and get out of it after that.
Locate the <iframe> with
iframe = driver.find_element_by_xpath("//iframe[@name='iframeName']") or whatever locator that it matches
Then switch_to the <iframe>:
driver.switch_to.frame(iframe)
If after that you need to continue anywhere out of the <iframe> switch out of it with
driver.switch_to.default_content()

Prophet
  • 32,350
  • 22
  • 54
  • 79
  • //a[contains(@href,'anaplan')] worked perfectly. However, it does not seem to work on another page, when that contains an iframe, as shown in the below paste.//a[contains(@href,'401068')] for example returns an error as unable to find the element, even though the href in the HTML definitely has that in it https://pastebin.com/D5Fzn6hu – user18139 May 04 '21 at 16:56
  • I updated the answer accordingly to ` – Prophet May 04 '21 at 17:06