何かというと、フロントがAngularJSでタグ生成されており
ファイルアップローダが通常のFileInputでされていないことが問題。
ファイルアップロードのトリガータグがaタグで実装されているため
sendkeyでtypeを実行できない、という状況で自動化するための備忘録。
※AngularJSなんだからおとなしくProtractor使えば?とか聞こえそうだけどね。。
さて今回試した方法
#sendkey出来ないので泥臭くブラウザ操作でFileアップロードダイアログ対応してみる
選択肢は以下の2つ
①Actionクラスで操作してみる
②Java Robotクラスで操作してみる
#まず①の場合
// Actionクラス対応版
// locateNameはタグのcssSelectorを指定
// valueはファイルアップロードのフルパス
private void inputFileAction(String locateName, String value){
if("".equals(value)) return;
click(By.cssSelector(locateName));
try{
//ダイアログ表示にタイムラグがあるので強制wait
Thread.sleep(2000);
Action action = new Actions(webDriverProvider.get())
.sendKeys(value)
.sendKeys(Keys.ENTER)
.build();
action.perform();
//アップロード完了までタイムラグがあるので強制wait
Thread.sleep(2000);
}catch(Exception e){
fail(e.toString());
}
}
結論:全く動かず。
なんかsendKeyがうまく機能してない。
でもダイアログボックスの「開く」にフォーカスが当たってるとこを見ると
何となく操作しようとする片鱗は見えるんだけど。
とりあえず悩む前にもう一つの方法を確かめてみる。
#次に②の場合
private void inputFileRobot(String locateName, String value){
if("".equals(value)) return;
click(By.cssSelector(locateName));
try{
//ダイアログ表示にタイムラグがあるので強制wait
Thread.sleep(2000);
setClipboardData(value);
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
//アップロード完了までタイムラグがあるので強制wait
Thread.sleep(2000);
}catch(Exception e){
fail(e.toString());
}
}
public static void setClipboardData(String string) {
StringSelection stringSelection = new StringSelection(string);
Toolkit.getDefaultToolkit()
.getSystemClipboard()
.setContents(stringSelection, null);
}
setClipboardDataで指定の文字列をクリップボードへ格納し
あとはRobotクラスで愚直にペースト操作と決定ボタンをキーボード操作。
結論:動く! 。。んだけど超不安定。
何が不安定かというと
そもそもJava Robotクラスがwebdriverと連動していないので
画面をちょっとでもいじっちゃうとRobotのターゲットウィンドウが移動してしまう。
結果として全く違うウィンドウにファイルフルパスがペーストされたり。。
この辺は強制的にフォーカスをwebdriverの画面に戻すとか改造しないと話にならない。
それはさておきJUnitRunnerを動かしてじっとしておけば動くことは確認できた。
#思ったこと
あまりにも無理やりすぎて自動テストという本懐からはかけ離れてしまった気がする。
詳しくないから知らないのだがProtractorならもっと簡単にいけたのかしら?
何にせよテスト自動化に関しては実装時に包括的に計画しないと
いろいろ工数かかり過ぎてシンドイなぁとしみじみ思った。
■補足■
参考までに実際の起動画面のhtmlを乗せておきます。
<div class="input-file text-inline">
<form action="/hogehoge/image/upload" method="post" enctype="multipart/form-data" target="hogehogeData.hogehogePath" class="ng-pristine ng-valid">
<input type="file" name="file" style="display: none;">
</form>
<span class="form-control uploadImgFileName w75"></span>
<span class="separator"></span>
<a class="btn btn-normal select-img">参 照</a>
</div>
input type="file" style="display: none;"
もうね、これのおかげですげー苦しんだ。