Làm thế nào để kiểm tra xem một phần tử có lớp bằng cách sử dụng Thước đo góc?


90

Tôi đang dùng thử Protractor để e2e kiểm tra ứng dụng Angular và chưa tìm ra cách phát hiện xem một phần tử có một lớp cụ thể hay không.

Trong trường hợp của tôi, bài kiểm tra nhấp vào nút gửi và bây giờ tôi muốn biết liệu biểu mẫu [name = "getoffer"] có lớp .ngDirty hay không. Các giải pháp có thể là gì?

describe('Contact form', function() {
    beforeEach(function(){
        browser.get('http://localhost:9000');
        element(by.linkText('Contact me')).click();
    });

    it('should fail form validation, all fields pristine', function() {
        element(by.css('.form[name="getoffer"] input[type="submit"]')).click();
        expect(element(by.name('getoffer'))).toHaveClass('ngDirty'); // <-- This line
    });
});

Câu trả lời:


110

Một điểm cần chú ý khi sử dụng toMatch(), như trong câu trả lời được chấp nhận, là các kết quả phù hợp từng phần. Ví dụ, giả sử bạn có một phần tử có thể có các lớp correctincorrectvà bạn muốn kiểm tra xem nó có lớp đó không correct. Nếu bạn đã sử dụng expect(element.getAttribute('class')).toMatch('correct'), điều đó sẽ trả về true ngay cả khi phần tử có incorrectlớp.

Đề xuất của tôi:

Nếu bạn chỉ muốn chấp nhận các kết quả phù hợp chính xác, bạn có thể tạo một phương thức trợ giúp cho nó:

var hasClass = function (element, cls) {
    return element.getAttribute('class').then(function (classes) {
        return classes.split(' ').indexOf(cls) !== -1;
    });
};

Bạn có thể sử dụng nó như thế này (tận dụng thực tế là expecttự động giải quyết các lời hứa trong Thước đo góc):

expect(hasClass(element(by.name('getoffer')), 'ngDirty')).toBe(true);

1
Điều này làm việc cho tôi, với mod đó tên lớp phải được gạch nối định dạng không trường hợp lạc đà, tức làexpect(hasClass(element(by.name('getoffer')), 'ng-dirty')).toBe(true);
Ackroydd

Tôi hơi không rõ về những gì hàm có lớp đang làm, đặc biệt là ở đâu hoặc những lớp nào khi được chuyển vào hàm .then, ai đó có thể khai sáng cho tôi không?
ErikAGriffin

@ErikAGriffin: Hàm hasClass nhận được hai đối số - một phần tử html và tên của một lớp cần kiểm tra. Sau đó, hàm nhận thuộc tính "class" (các lớp) mà phần tử có. Nó tách chuỗi lớp để lấy một mảng các lớp. Sau đó, nó sẽ kiểm tra xem lớp bạn đang tìm có nằm trong bất kỳ chỉ mục dương nào của mảng hay không. Tôi cho rằng đó là một cách để kiểm tra sự tồn tại.
VSO

Tôi đã viết lại hàm bốn dòng của bạn cho một lớp lót ES6 sexy này: hasClass = (element, className) => element.getAttribute ('class'). Then ((class) => class.split ('') .indexOf ( className)! == -1);
Laurens Mäkel

Trong TypeScript: hàm async hasClass (elm: ElementFinder, className: string): Promise <boolean> {const classNamesStr: string = await elm.getAttribute ('class'); const classNamesArr: string [] = classNamesStr.split (''); trả về classNamesArr.includes (className); }
tedw

56

Nếu bạn đang sử dụng Thước đo góc với Jasmine, bạn có thể sử dụng toMatchđể đối sánh như một biểu thức chính quy ...

expect(element(by.name('getoffer')).getAttribute('class')).toMatch('ngDirty');

Ngoài ra, lưu ý rằng nó toContainsẽ khớp với các mục trong danh sách, nếu bạn cần.


1
Tôi không chắc chắn nếu đó là cách lý tưởng để làm điều này, nhưng ít nhất nó hoạt động như mong đợi :)
Allan quần áo rách

1
Không, tôi nói có lẽ là không. Tôi mong đợi elementđể trả lại một đối tượng với một hasClassphương pháp mà bạn có thể bọc bên trong một expectcuộc gọi ...
ryan.l

2
toContaincó thể là một lựa chọn tốt hơn toMatchtrong trường hợp này.
TrueWill

Nếu bạn muốn đề phòng các trận đấu một phần, hãy thử một cái gì đó như /(^|\s)ngDirty($|\s)/.
Andrew Myers

bạn có thể có thể sử dụng .not.toContainđể kiểm tra xem nó không có lớp cụ thể hoặc .toContainđể kiểm tra xem nó có tồn tại hay không
Jack

18

Đơn giản nhất là:

expect(element.getAttribute('class')).toContain("active");

Điều này trả lại lỗi java.util.ArrayList cannot be cast to java.lang.Stringtrên Microsoft Edge
Manolis

@Manolis làm cách nào để bạn nhận được các ngoại lệ java trong bảng điều khiển web cho anglejs ??
vasia

4

Dựa trên câu trả lời từ Sergey K, bạn cũng có thể thêm một trình đối sánh tùy chỉnh để thực hiện việc này:

(coffeescript)

  beforeEach(()->
    this.addMatchers({
      toHaveClass: (expected)->
        @message = ()->
          "Expected #{@actual.locator_.value} to have class '#{expected}'"

        @actual.getAttribute('class').then((classes)->
          classes.split(' ').indexOf(expected) isnt -1
        )
    })
  )

Sau đó, bạn có thể sử dụng nó trong các thử nghiệm như sau:

expect($('div#ugly')).toHaveClass('beautiful')

Và bạn sẽ gặp lỗi sau nếu không:

 Message:
   Expected div#ugly to have class beautiful
 Stacktrace:
   Error: Expected div#ugly to have class 'beautiful'

3

Bạn đã thử ...

var el = element(by.name('getoffer'));
expect(e.getAttribute('class')).toBe('ngDirty')

hoặc một biến thể của trên ...


5
Vấn đề là, biểu mẫu có nhiều hơn một lớp được gắn vào.
Allan Tatter

2

Tôi đã thực hiện đối sánh này, tôi phải gói nó trong một lời hứa và sử dụng 2 lần trả lại

this.addMatchers({
    toHaveClass: function(a) {
        return this.actual.getAttribute('class').then(function(cls){
            var patt = new RegExp('(^|\\s)' + a + '(\\s|$)');
            return patt.test(cls);
        });
    }
});

trong thử nghiệm của tôi bây giờ tôi có thể làm stuf như thế này:

   var myDivs = element.all(by.css('div.myClass'));
   expect(myDivs.count()).toBe(3);

   // test for class
   expect(myDivs.get(0)).not.toHaveClass('active');

điều này cũng hoạt động khi một phần tử có nhiều lớp hoặc khi một phần tử không có thuộc tính lớp nào cả.


1

Dưới đây là một Jasmine 1.3.x tùy chỉnh toHaveClasskhớp với phủ định .nothỗ trợ cộng chờ lên đến 5 giây (hoặc bất cứ điều gì bạn chỉ định).

Tìm đối sánh tùy chỉnh đầy đủ sẽ được thêm vào khối onPrepare của bạn trong ý chính này

Sử dụng mẫu:

it('test the class finder custom matcher', function() {
    // These guys should pass OK given your user input
    // element starts with an ng-invalid class:
    expect($('#user_name')).toHaveClass('ng-invalid');
    expect($('#user_name')).not.toHaveClass('ZZZ');
    expect($('#user_name')).toNotHaveClass('ZZZ');
    expect($('#user_name')).not.toNotHaveClass('ng-invalid');
    // These guys should each fail:
    expect($('#user_name')).toHaveClass('ZZZ');
    expect($('#user_name')).not.toHaveClass('ng-invalid');
    expect($('#user_name')).toNotHaveClass('ng-invalid');
    expect($('#user_name')).not.toNotHaveClass('ZZZ');
});

1
function checkHasClass (selector, class_name) {
    // custom function returns true/false depending if selector has class name

    // split classes for selector into a list
    return $(selector).getAttribute('class').then(function(classes){
        var classes = classes.split(' ');
        if (classes.indexOf(class_name) > -1) return true;
        return false;
    });
}

Đây là cách tôi làm điều đó ít nhất, mà không cần phải sử dụng hàm mong đợi. Hàm này chỉ trả về true nếu lớp nằm bên trong phần tử và false nếu không. Điều này cũng sử dụng các lời hứa, vì vậy bạn sẽ sử dụng nó như:

checkHasClass('#your-element', 'your-class').then(function(class_found){
    if (class_found) console.log("Your element has that class");
});

Chỉnh sửa: Tôi chỉ nhận ra rằng điều này về cơ bản giống với câu trả lời hàng đầu


1

Một cách để đạt được điều này là sử dụng xpath và sử dụng contains()

Thí dụ:

var expectElementToHaveClass = function (className) {
    var path = by.xpath("//div[contains(@class,'"+ className +"')]");
    expect(element.all(path).count()).to.eventually.be.eq(1);
};

0

Bạn có thể sử dụng trình phân tích cú pháp CSS để xử lý điều này bằng cách kiểm tra xem phần tử có lớp đã cho có tồn tại hay không:

expect(element(by.css('.form[name="getoffer"].ngDirty')).isPresent()).toBe(true);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.