각도기를 사용하여 요소에 클래스가 있는지 테스트하는 방법은 무엇입니까?


90

나는 각도 앱을 e2e 테스트하기 위해 각도기를 시도하고 있으며 요소에 특정 클래스가 있는지 여부를 감지하는 방법을 찾지 못했습니다.

제 경우에는 테스트에서 제출 버튼을 클릭하고 이제 form [name = "getoffer"]에 .ngDirty 클래스가 있는지 알고 싶습니다. 해결책은 무엇일까요?

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
    });
});

답변:


110

toMatch()허용되는 답변에서 와 같이 using을 사용하여 찾아야 할 한 가지 문제 는 부분 일치입니다. 예를 들어, 당신이 클래스를 가질 수 요소가 있다고 가정하자 correctincorrect, 당신은이 클래스를 가지고 테스트 할 correct. 을 사용 expect(element.getAttribute('class')).toMatch('correct')하면 요소에 incorrect클래스 가 있어도 true를 반환합니다 .

나의 제안:

정확히 일치하는 항목 만 허용하려면 이에 대한 도우미 메서드를 만들 수 있습니다.

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

다음과 같이 사용할 수 있습니다 ( expectProtractor에서 자동으로 약속을 해결 한다는 사실을 활용 ).

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

1
이것은 클래스 이름이 낙타 대소 문자가 아닌 하이픈 형식이어야한다는 모드로 저에게 expect(hasClass(element(by.name('getoffer')), 'ng-dirty')).toBe(true);
효과적이었습니다.

나는 함수가 클래스가 무엇을하고 있는지, 특히 .then 함수에 전달할 때 클래스가 어디에 또는 무엇인지 명확하지 않습니다. 누군가 나를 계몽 할 수 있습니까?
ErikAGriffin 2015 년

@ErikAGriffin : hasClass 함수는 두 개의 인수, 즉 html 요소와 확인할 클래스 이름을 전달받습니다. 그런 다음 함수는 요소가 가진 "class"속성 (클래스)을 가져옵니다. 클래스 배열을 얻기 위해 클래스 문자열을 분할합니다. 그런 다음 찾고있는 클래스가 배열의 양수 인덱스에 있는지 확인합니다. 존재를 확인하는 방법이라고 생각합니다.
VSO

이 섹시한 ES6 한 라이너에 네 줄 함수를 다시 작성했습니다. hasClass = (element, className) => element.getAttribute ( 'class'). then ((classes) => classes.split ( '') .indexOf ( className)! == -1);
Laurens Mäkel

TypeScript에서 : 비동기 함수 hasClass (elm : ElementFinder, className : string) : Promise <boolean> {const classNamesStr : string = await elm.getAttribute ( 'class'); const classNamesArr : string [] = classNamesStr.split ( ''); return classNamesArr.includes (className); }
tedw

56

Jasmine과 함께 Protractor를 사용 toMatch하는 경우 정규식으로 일치 하는 데 사용할 수 있습니다 .

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

또한 toContain필요한 경우 목록 항목과 일치합니다.


1
나는 확실하지가이 작업을 수행 할 수있는 이상적인 방법의 경우 해요,하지만 적어도 그것은 :) 기대 작품으로
앨런 갈가리 찢어지다

1
아니, 아마 그렇지 않다고 말하고 싶습니다. 나는 기대 element을 가진 객체 반환 hasClass당신이 내부에 포장 할 수 방법 expect... 전화
ryan.l

2
toContaintoMatch이 경우 보다 더 나은 선택 일 수 있습니다 .
TrueWill 2015-08-10

부분 일치를 방지하려면 /(^|\s)ngDirty($|\s)/.
Andrew Myers

당신은 아마 사용할 수 .not.toContain는 특정 클래스 또는없는 경우 확인 .toContain검사를 위해이 존재하는 경우

18

가장 간단한 것은 :

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

java.util.ArrayList cannot be cast to java.lang.StringMicrosoft Edge에서 오류 를 반환합니다
Manolis

@Manolis angularjs의 웹 콘솔에서 Java 예외를 어떻게 얻습니까 ??
vasia

4

Sergey K의 답변을 기반으로 사용자 정의 매처를 추가하여이를 수행 할 수도 있습니다.

(커피 스크립트)

  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
        )
    })
  )

그런 다음 다음과 같은 테스트에서 사용할 수 있습니다.

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

그렇지 않은 경우 다음 오류가 발생합니다.

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

3

시도해 보셨습니까 ...

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

또는 위의 변형 ...


5
문제는 양식에 둘 이상의 클래스가 첨부되어 있다는 것입니다.
Allan Tatter 2013

2

이 매처를 만들었는데 약속에 싸서 2 번 돌려야 했어요

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

내 테스트에서 이제 다음과 같이 stuf를 할 수 있습니다.

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

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

이것은 요소에 여러 클래스가 있거나 요소에 클래스 속성이 전혀 없을 때도 작동합니다.


1

여기toHaveClass부정을 .not지원 하는 Jasmine 1.3.x 사용자 지정 매 처가 있으며 최대 5 초 (또는 사용자가 지정한대로)를 기다립니다.

이 요점에서 onPrepare 블록에 추가 할 전체 사용자 지정 매처를 찾습니다.

샘플 사용법 :

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;
    });
}

이것은 예상 기능을 사용할 필요없이 적어도 내가하는 방법입니다. 이 함수는 클래스가 요소 내부에 있으면 true를 반환하고 그렇지 않으면 false를 반환합니다. 이것은 또한 promise를 사용하므로 다음과 같이 사용합니다.

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

편집 : 나는 이것이 본질적으로 최상위 답변과 동일하다는 것을 깨달았습니다.


1

이를 달성하는 한 가지 방법은 xpath를 사용하고 contains()

예:

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

0

CSS 파서를 사용하여 주어진 클래스의 요소가 존재하는지 확인하여이를 처리 할 수 ​​있습니다.

expect(element(by.css('.form[name="getoffer"].ngDirty')).isPresent()).toBe(true);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.