トップ «前の日記(2006-02-06) 最新 次の日記(2006-02-15)» 編集

活動日誌


2006-02-07

[Selenium]テストを JavaScript で記述した際に、改行を含めると Firefox で動かない件

Selenium では、フィールドを JavaScript で記述することができます。 例えば

<tr>
  <td>verifyText</td>
  <td>hoge</td>
  <td>javascript{var d = new Date(); d.getFullYear()}</td>
</tr>

は、JavaScript が解釈されて

<tr>
  <td>verifyText</td>
  <td>hoge</td>
  <td>2006</td>
</tr>

とみなされます(2006年の場合)。値を動的に決定したいときには便利です。

ところが、これに

<tr>
  <td>verifyText</td>
  <td>hoge</td>
  <td>javascript{var d = new Date();
d.getFullYear()}</td>
</tr>

のように改行を入れてしまうと、IE6 だと動くのですが、Firefox 1.5 だと動かな くなってしまうのに気がつきました。

この原因を調べてみました。

`javascript' というキーワードに反応して JavaScript が実行されるので、 js ファイルに対して `javascript' で grep してみると、selenium-api.js に処理があることが分かりました。Selenium.preprocessParameter がそれで す。

Selenium.prototype.preprocessParameter = function(value) {
    var match = value.match(/^javascript\{(.+)\}$/);
    if (match && match[1]) {
        return eval(match[1]).toString();
    }
    return this.replaceVariables(value);
}

テストの JavaScript 文に改行を入れたときこの関数に渡ってくる値を alert で見てみました。すると、IE だと改行がなくなっているのに対し、Firefox では改行が そのまま入っているのが分かりました。

preprocessParameter は selenium-executionloop.js の中にある TestLoop.executeCurrentCommand から呼び出されていて、引数には command.target と command.value という値が渡されています。

この command オブジェクトの出自を調べていくと、 selenium-testrunner.js の

function nextCommand() {
    var row = currentTest.nextCommand();
    if (row == null) {
        return null;
    }
    row.cells[2].originalHTML = row.cells[2].innerHTML;
    return new SeleniumCommand(getText(row.cells[0]),
                               getText(row.cells[1]),
                               getText(row.cells[2]));
}

にたどりつきます。さらに getText は htmlutils.js で定義されていて、 その定義は次のようになっています。

function getText(element) {
    text = "";

    if(element.textContent) {
        text = element.textContent;
    } else if(element.innerText) {
        text = element.innerText;
    }
    // Replace &nbsp; with a space
    // TODO - should this be in the match() code instead?
    text = text.replace(/\240/g, " ");
    return text.trim();
}

これで大本にたどりつきました。 textContent と innerText について IE と Firefox での挙動を調べてみると

  • IE では innerText のみが定義されている。改行は取り除かれている。
  • Firefox では textContent のみが定義されている。改行が含まれる。

という結果になりました。(ちなみに、element.firstChild.nodeValue にしても改行に関しては同じ結果です)

よって元に戻ると、preprocessParameter で

var match = value.match(/^javascript\{(.+)\}$/);

によって javascript の処理をするかどうかを判定する際、 `.' が改行にマッチしないために IE と Firefox によってテストの挙動が変 わっていたということになります。

正規表現でのマッチの際、文字列に改行が含まれうることを考慮して

var match = value.match(/^javascript\{((.|\r?\n)+)\}$/);

にすると、Firefox でも javascript{ ... } の中に改行を含めることができ ました。


2005|02|03|04|05|06|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|03|04|05|06|10|
2008|04|10|
2009|10|
2010|05|08|
2012|01|02|03|
2014|01|
2022|05|
トップ «前の日記(2006-02-06) 最新 次の日記(2006-02-15)»