Code

2014年10月31日金曜日

IE8 AngularJS & jQuery ui - problem -> ng-non-bindable の使い方

 昨日、隣のチームから変なバグが聞かれました。具体的に、jQuery ui の datepicker が IE8 では動かなくなった。まぁ、最新版の AngularJS は IE8 サポートしてないから、問題ないけど、今のプロジェクトでは 1.0.8 を使ってるし、IE8 もサポート対象ブラウザーなので。。。あ〜頭が痛くなる。。。
 jQuery の datepicker のサープルを IE8 で開いて、動きは正しいようです。多分、AngularJS と jQuery ui の間に何か干渉が起きたと思われました。HTML を見てみたら、各日付の <td> tag 中の <a> に <!-- IE fix --> コメントが追加されたことが気づきました。AngularJS には <a> tag を IE8 での特別処理が入ってるようです。
       // add a comment node to anchors to workaround IE bug that causes element content to be reset
      // to new attribute content if attribute is updated with value containing @ and element also
      // contains value with @
      // see issue #1949

つまり、AngularJS は上記の IE fix コメントを追加したのです。一般的なライブラリは innerHTML を使って、タグの内容を取得すると、その IE fix も一緒に取得されるのです。parseInt などを使うと、エクセプションが throw されます。本来数字のみ入っている場所に他の文字列が入ったので、何か起きると、不思議ではない。
 
 もう少し調べてみたら、Angular は ng-non-bindable という directive を提供しています。これを使うと、 Angular は HTML DOM をスキャンする時、そのブロックをスキップさせます。つまりその中にある要素は Angular の $digest サイクルに入らない。
 これで、Angular は勝手に <a> tag 何かを入れることがなくなります。問題解決。

 今後 IE 8 をサポートしている間、気をつけないと。
 それでは。

2014年10月18日土曜日

Protractor での自動テスト

 先週から、検証チームを助けて、Protractor での自動テストが始めました。先日ダウンロードして、インストールしようと思ったんですけど、npm がなぜかshanum エラーが出ました。調べたら、ネットワークのせいかもしれないと、もう一回インストールして、無事成功しました。
 Protractor を動かすには、まず Selenium サーバーを起動して、config ファイルにそのアドレスと、spec の場所を入れて、後、Jasmine sytax での spec が必要です。
 Protractor とともに、webdriver-manager と言う Node のコマンドがインストールされます。webdriver-manager update を実行すると、google から chromedriver.exe, IEserverdriver.exeと、Selenium jar ファイルがダウンロードされます。その後、webdriver-manager start で selenium サーバーが起動されます。Jetty なんちゃら 4444 がコンソールに表示されたら、起動成功。
 その後、config に下記の JSON を記入して、spec を書いて、すぐ実行できるようになります。
exports.config = {
  seleniumAddress: 'http://localhost:4444/wd/hub',
  specs: ['todo-spec.js']
};
spec のサンプル:
describe('angularjs homepage todo list', function() {
  it('should add a todo', function() {
    browser.get('http://www.angularjs.org');

    element(by.model('todoText')).sendKeys('write a protractor test');
    element(by.css('[value="add"]')).click();

    var todoList = element.all(by.repeater('todo in todos'));
    expect(todoList.count()).toEqual(3); browser.sleep(3000);
    expect(todoList.get(2).getText()).toEqual('write a protractor test');
  });
});
protractor conf.js を実行すれば、angular のウェブページが表示されて、TODO に自動的に一つアイテムを追加されて、その後、 TODO の数をチェックして、終了。

 注意すべきところは、protractor は selenium のラッバーみたいなもので、AngularJS 終了を待ってから、コマンドを実行してます。(おそらく、Angular の phase をチェックしてるかもしれない)、もし、ウェブページに Angular がなければ、変なエラーが出るのです。原因は protractor ずっと待ってて、待ち続けて、タイムアウトになります。
 このとき、browser.get や element などが使えなくなります。browser.driver を使うべきです。browser.driver は webdriver js で、findElement などが使えます。この時、適当に sleep を入れて、JS の実行完了や、ajax の実行などを自分でまつ必要になります。。。
 やはり、protractor が使いやすいですね。
 
 後日、また続きを。それでは。

Android WebView の 動画が遅い件

 先日、新しい Ads のパフォーマンスが良くないなと思っただけで、今日は他のチームも発見して、相談されました。具体的には WebView を使って、HTML ファイルを表示してますが、画像では iOS, Android 両方問題なく、良く表示されてますが、動画の場合、ある Android 機器が超遅くて、遅くて、使い物になれないほどです。
 実際、Web Inspect で見てみると、JS の実行が遅いです。じゃ、 CSS ではどうでしょうと思って、ほぼすべてのコードを書き換えて、CSS でアニメーションを実現して、試しました。。。でも、遅いです。。。CSSの場合、ハードウェアの加速があるので、速いと言われていますが、Android ではそうではないそうです。まぁ、機器のスペクもよるので、Nexus 5 で試しましたが、iOS ほどスムーズではないですが、そこそこ動いています。
 こう見ると、多分古い Android 機器はだめみたいです。。。何でだろうと思って、やはり WebView はブラウザーより遅くて、開発時は注意しないと。
 一応メモして、将来何か参考になるかもしれないです。
 それでは。