Georgi Antonov
Georgi Antonov

Reputation: 1641

How to select td element inside table using css and specific text inside td

Lets say i have the following tbody which represents a calendar in this calendar i have many td with text inside like this :

    <tbody>
     <tr>
      <td>31</td>
      <td>1</td>
      ...
     </tr>
     <tr>
      <td>8</td>
      <td>9</td>
      ...
     </tr>
    </tbody>

Lets say I want to click all the options in a particular month without clicking the options which moves to next or previous month, and I used this

for (var i=1;i<32;i++){

            element(by.css('body > div:nth-child(7) > div.calendar.left.single > div.calendar-table > table > tbody td')).element(by.buttonText(i)).click();
        }

this is selector path to the tbody : body > div:nth-child(7) > div.calendar.left.single > div.calendar-table > table > tbody td

But .element(by.buttonText(i)).click(); does not work I guess buttonText isnt working for td elements

EDITS : Right now its working except that when iterating through second loop it gives me error : element not visible while it is visible...

Page.js

var Page = function() {
    var that = this;
    //ELEMENTS
    this.from = element(by.xpath('//*[@id="html"]/body/app/div/layout/div/app-tabs/div/div/div/div/app-tabs-page/app-tabs-page-content/tcmetadata/div/div/div[1]/div[1]/tc-filters/div/form[2]/div[1]/label/input'));
    this.to = element(by.xpath('//*[@id="html"]/body/app/div/layout/div/app-tabs/div/div/div/div/app-tabs-page/app-tabs-page-content/tcmetadata/div/div/div[1]/div[1]/tc-filters/div/form[2]/div[2]/label/input'));

    //EVENTS
    this.clickElements = function(els){
        els.each(function (el){
            el.click();
        });
    }
    this.clickElement = function(el){
        el.click();
    }
};
module.exports = new Page;

test.js:

var page = require('./Page');
    it('should ask any question', function() {

        for (var i=1;i<15;i++){
            page.clickElement(page.from);

            element(by.xpath('//*[@id="html"]/body/div[1]/div[1]/div[2]/table/tbody')).element(by.xpath('//td[text()='+i+']')).click();
            for (var j=i; j<15;j++){
                page.clickElement(page.to);
                browser.sleep(1000);
                element(by.xpath('//*[@id="html"]/body/div[2]/div[1]/div[2]/table/tbody')).element(by.xpath('//td[text()='+j+']')).click();
            }

        }

    });

The first loop works but when it goes into the second loop i get an error "element not visible" with browser.sleep i can see its visible

Upvotes: 2

Views: 2996

Answers (1)

Florent B.
Florent B.

Reputation: 42518

You could use cssContainingText to combine a CSS selector with a text condition:

var calendar = element(by.css('body > div:nth-child(7) > div.calendar.left.single > div.calendar-table > table > tbody'));
for (var i = 1; i < 32; ++i) {
    calendar.element(by.cssContainingText('td', i.toString())).click();
}

You could also use an XPath to find the text:

var calendar = element(by.css('body > div:nth-child(7) > div.calendar.left.single > div.calendar-table > table > tbody'));
for (var i = 1; i < 32; ++i) {
    calendar.element(by.xpath(".//td[text()='" + i + "']")).click();
}

And to make it faster, I would evaluate the number within the XPath:

var calendar = element(by.css('body > div:nth-child(7) > div.calendar.left.single > div.calendar-table > table > tbody'));
var months = calendar.all(by.xpath(".//td[text() > 0 and text() < 32]"));
months.each(e => e.click());

Upvotes: 1

Related Questions