要素にProtractorを使用してクラスがあるかどうかをテストする方法は?


90

Angularアプリをe2eテストするためにProtractorを試してみましたが、要素に特定のクラスがあるかどうかを検出する方法がわかりませんでした。

私の場合、テストは送信ボタンをクリックし、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()受け入れられた回答のように、を使用して注意しなければならない1つの問題は、部分一致です。たとえば、クラスcorrectとを含む可能性のある要素があり、クラスがincorrectあることをテストするとします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;
    });
};

次のように使用できます(expect分度器でPromise を自動的に解決するという事実を利用しています)。

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要素とチェックするクラスの名前という2つの引数が渡されます。次に、関数は要素が持つ「クラス」属性(クラス)を取得します。クラス文字列を分割して、クラスの配列を取得します。次に、探しているクラスが配列の正のインデックスにあるかどうかをチェックします。それは存在を確認する方法だと思います。
VSO、2015

4行の関数をこのセクシーなES6の1行に書き換えました:hasClass =(element、className)=> element.getAttribute( 'class')。then((classes)=> classes.split( '').indexOf( className)!== -1);
LaurensMäkel18年

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

ジャスミンで分度器を使用している場合toMatch、正規表現として照合するために使用できます...

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

また、toContain必要に応じて、リストアイテムと一致します。


1
それがこれを行う理想的な方法かどうかはわかりませんが、少なくとも期待どおりに機能します:)
Allan Tatter

1
いいえ、おそらくそうではありません。私はメソッド内のelementオブジェクトを返すと思いhasClassますが、それをexpect呼び出しの内側にラップできます...
ryan.l

2
toContaintoMatchこの場合よりも良い選択かもしれません。
TrueWill、2015

部分一致を防ぎたい場合は、などを試してください/(^|\s)ngDirty($|\s)/
アンドリューマイヤーズ

おそらく.not.toContain、特定のクラスがない.toContainかどうか、または存在するかどうかをチェックするために使用できます
Jack

18

最も簡単です:

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

これはjava.util.ArrayList cannot be cast to java.lang.String、Microsoft Edgeでエラーを返します
Manolis

@Manolis angularjsのWebコンソールで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サポートと最大5秒(または指定したもの)まで待機するJasmine 1.3.xカスタムマッチャーです。

この要点の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;
    });
}

これは、expect関数を使用する必要なしに、少なくとも私が行う方法です。この関数は、クラスが要素内にある場合はtrueを返し、そうでない場合はfalseを返します。これもプロミスを使用するため、次のように使用します。

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

編集:私はこれが本質的にトップアンサーと同じであることに気づきました


1

これを実現する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.