BDD Frameworkでテスト中に、OutSystems UIのActionを使ったら、「OutSystems is not defined」というJavaScriptエラーが発生した。
発生原因と対策を以下にまとめる。
環境情報
ODC Studio (Version 1.5.28)
OutSystems UI (Version 2.23.0)
BDD Frameworkで発生した問題
テスト画面でOutSystems UIのScrollToElement Actionを使うとエラーになる
ブラウザでテスト画面を開いたら、画面下部までスクロールさせるため、OutSystems UIのUtilities/ScrollToElement Actionを呼んだ。
この時、以下のようなエラーが出た。
エラーメッセージから、恐らく
「JavaScriptのOutSystemsというObjectが定義されていないのにアクセスしている」
→「OutSystemsという名前から、プラットフォームが提供する部品のJavaScriptライブラリであり、発生したタイミング(OutSystems UIのActionを呼んだ)からOutSystems UIのJavaScriptライブラリが読み込まれていない」のであろうという推測はできる。
以下、実際の原因を確認し、対策を検討する。
補足:なぜScrollToElementを使いたかったのか
BDD Frameworkは、OutSystemsのユニットテストツール。
OutSystemsの画面として自動テストケースを作成するのだが、画面に配置した全ケースが成功したかを確認するために、画面下部に配置したFinalResult Blockの位置までスクロールする必要がある。
テストケース開発中は頻繁にテスト画面を開くため、毎回画面下部までスクロールするのが面倒で、自動的にスクロールさせたかった。
原因調査:OutSystems UIのJavaScriptライブラリが読み込まれていないことが原因
ブラウザの開発者ツールを使ってJavaScriptエラーを確認
ブラウザでF12キーを入力すると開発者ツールが開く。
JavaScriptエラーが発生した場合、開発者ツールのコンソールタブにエラー内容が表示される。
OS-CLRT-00000 [Application] OutSystems is not defined
エラーの種類がReferenceErrorであることも確認できたので、OutSystemsというObjectがどこかでアクセス不能であることがわかる。
場合によっては、コンソールタブで表示されるStackの情報がエラー箇所の特定に役立つこともあるのだが、今回は不発。
ScrollToElementの実装から"OutSystems"にアクセスしている場所を特定
ODC Studioで参照したScrollToElementを選択→右クリック→Open in OutSystems UIを選択すると、CloneしたLibraryを開ける。
Action先頭のJavaScript要素に以下のコードが記述されていた。
つまり「OSUI」(名前から当然にOutSystemsのライブラリが配置されるObjectだろう)の親Objectと思われる。これがないことから、シンプルにOutSystems UIのJavaScriptライブラリがロードされていないものと思われる。
$parameters.Response = OutSystems.OSUI.Utils.ScrollToElement(
$parameters.WidgetId,
$parameters.IsSmooth,
$parameters.OffSet,
$parameters.ElementParentClass,
$parameters.ScrollDelay
);
ではなぜ、普通の画面ではライブラリがロードされ、BDD Frameworkの画面ではされないのか?
ここで視点を変えて、↑のことを考えてみる。
普通の画面とBDD Frameworkの画面を比較することで、何が抜けると「OutSystems is not defined」が発生するかを調べる。
普通の画面:標準のWeb Appを選択して作ったApp内で、EmptyのScreen Templateを元に作成した画面
BDD Frameworkの画面:「BDD Framework」のCustom Application Templateを選択して作成したApp内の、ScreenTemplates (UI Flow) > New_Suiteをコピーした画面
どこを比較するか? OutSystems UIは一般的に、画面ライフサイクルのどこでも使う可能性がある。つまり、初期処理(恐らくOn InitializeかOn Ready)で読み込まれているはず。また、どの画面にも同じ設定を適用することから、恐らくLayout Blockで行われている。
というわけで、それぞれの画面で使っているLayout BlockのOn Initialize, On Readyを調べてみる。
すると、「普通の画面」のOn Readyで、OutSystems UIのLayoutReadyというそれらしいActionを呼んでいることがわかった。
LayoutReadyの実装を確認すると、先頭でLoadOutSystemsUIScript Actionを呼んでいる。名前からしてこれがOutSystems UIのJavaScriptライブラリを読み込むための処理。
Layout BlockのOn ReadyでLayoutReadyを呼んでいないのが原因で、BDD Framework画面でOutSystems UIのScrollToElementを呼んだ時にエラーが出ていた。
LoadOutSystemsUIScriptの実装を確認
以下のコードでライブラリがロードされていないことを確認した上で(つまりこのActionは繰り返し呼んでも害がない)、
$parameters.HasScript = window.OutSystems !== undefined && window.OutSystems.OSUI !== undefined;
以下のコードでロードしている。$parameters.URLには、OutSystems UI内に配置されたOutSystemsUIライブラリのURLが渡される。
// Require the OutsystemsUI.js
$actions.RequireScript($parameters.URL).then(function(){
$parameters.Success = true;
}).catch(function(e){
$parameters.Success = false;
console.warn('The OutSystemsUI.js wasn\'t successfully required');
}).finally(function(){
$resolve();
})
対策: 画面かLayout BlockでOutSystems UI/LayoutReady Actionを呼ぶ
BDD Frameworkの問題の画面では、BlockのOn ReadyでLayoutReadyを呼べば良い。
普通の画面でこのエラーが起きている場合、恐らくLayout Blockを手作りしてOn Readyをコピーするのを忘れたのだろう。一応意図を確認して、意図的に外したのでないのなら、テンプレートから作ったAppのLayout BlockからOn Readyをコピーしてくれば良い。
補足: OutSystems UIの一部PatternはRequired ScriptsでOutSystemsUIライブラリを読み込んでいる
例えばGallery。こういうPatternを使う時はLayoutReadyしなくても大丈夫かもしれない。Required Scriptsで読み込むものとそうでないものがあるので、やはり、基本的にはLayot BlockでLayoutReadyを呼んだほうがいいだろう。