Protractorを利用していていろいろノウハウが溜まってきたので、残しておきます。
Angular.jsではないフレームワーク(knockout.jsを使ってます)を使って画面を構築しているアプリで、いい感じにテストできるように改善しています。
Angular.jsではないフレームワークで利用するために
Angular.jsとの同期を切る
まずはAngular.jsとの同期をオフにしておきます。
ProtractorはAngular.js用のE2Eフレームワークなので、Angular.jsの初期化が終わるまで待つ処理がデフォルトで入っています。
Angular.jsを利用していない場合にはオフにしておかないとエラーになります。
また、URLをgetする前に実行しておかないと意味ないので、注意しましょう。
browser.ignoreSynchronization = true;
browser.get( url );
エレメントを取得するとき、エレメントの存在チェックをする
knockout.jsなどのフレームワークでは、htmlを読み込んだタイミングでは、まだDOMが構築されておらず、非同期でいろいろな情報を取ってきたりしてからDOMを構築する、というような処理を行います。
ProtractorなどのE2Eテストフレームワークでは、htmlの読み込みが完了した時点でテストケースを実行するように作られているので、DOMの構築が終わっていない状態でテストを実行してしまう可能性があります。
そこで、エレメントに対して何か処理をする際、エレメントが見つかるまで待つ、という処理を入れてあげます。
elementWrapper = function( locator ) {
browser.wait( function() {
return browser.findElement( locator ).then( function( element ) {
return element.isDisplayed().then( function( isDisplayed ) {
return isDisplayed;
} );
} )
.catch( function( e ) {
return false;
} );
} );
return element( locator );
};
// element( by.id( "login" ) ).click();
elementWrapper( by.id( "login" ) ).click();
テストコードを書きやすくする
イベントをシミュレートできるようにする
Protractorではエレメントに対してクリックか文字入力くらいしかできませんが、スマホ対応しているアプリなどは、タッチイベントなども入力したいですね。
なので、jqueryのイベントを発生させられるようにします(アプリ側でjQueryが動作していないと利用できませんが)。
ElementFinderがelement( hogehoge )
の戻り値なので、こいつにメソッドを追加してやります。
browser.executeScriptを使えば、ブラウザ上で好きなコードを実行することができます。
$( "#login" ).on( "touchstart", function() {
console.log( "start" );
} );
$( "#login" ).on( "touchend", function() {
console.log( "end" );
} );
ElementFinder.prototype.simulate = function( event ) {
this.getWebElement().then( function( element ) {
browser.executeScript( function( el, e ) {
$( el ).trigger( e );
}, element, event );
} );
};
// 1.5秒 エレメントを長押しする
element( hoge ).simulate( "touchstart" );
browser.sleep( 1500 );
element( hoge ).simulate( "touchend" );
これで、クリックだけでなくイベントを発生させることができるようになりました。