もっと詳しく

こんにちは、 Gaji-Labo フロントエンドエンジニアの茶木です。

cypress に最近ガッツリと挑戦しています。新しいことがわかると楽しいですね。

inputへの長文の入力テストを書くときのちょっとしたテクニックです。
結論はまとめをご覧ください!

type を使った普通の書き方

cy.get("input").eq(0).type("入力テスト");

普通に input にテキストの入力を書くときのテストはこれでOKです。

type のちょっと気になる点

// LONG_LONG_TEXT: 2000文字くらいのテキスト
cy.get("input").eq(0).type(LONG_LONG_TEXT);

input の最大入力文字数の制限チェックのテストを書きたければ、type の引数に長い文字列を指定することになるでしょう。

記述上の問題はないのですが、2000文字程度のテキストを type で入力するテストを実際に実行するとデフォルトで20秒程度要します。なかなか遅い!

なぜ実行に時間がかかるのか?

なぜ実行に時間がかかるのでしょうか。これは、type メソッドは、キーボードのタイピングを模したテストだからです。デフォルトの設定では type は1文字につき入力後に10msの遅延が設定されています。

人間のキー入力と比較したらかなり早いですが、それでも2000文字の入力をすると20秒かかってしまうというわけです。

delay を設定する(うまくいかない)

cy.get("input").eq(0).type(LONG_LONG_TEXT, {delay: 1});

参考: https://docs.cypress.io/api/commands/type

type の デフォルトのキー入力の遅延時間が 10ms なのは 第2引数の options で変更ができますが、実際には遅延は0にはならず、やはり実行には時間がかかります。

まとめ(解決法)

cy.get("input").eq(0)
  .invoke("val", LONG_LONG_TEXT)
  .type("!");

先にソースを示します。これで、通常のキー入力は 代替ができます。
重要なのは以下の2つです。

動作原理

  • invoke: 遅延を発生させずにinputに入力を行う
  • type: input の onChange イベントを発生させる

invoke

invoke はメソッドを呼び出すメソッドです。第1引数の val が呼び出すメソッドで jQueryval と同様に働き、つまり input 要素の value に 直接長いテキストを入れる動作になります。キーボードを介さないので遅延がありません。

type

invoke は キー入力のイベントを発生させないため、キー入力の onChange イベントを発生させるためにtype を呼んでいます。React では input の内容の変化に起因する動作は、イベントをトリガーに実行するので、最後の1キーの入力だけ type で行っているということです。

参考:https://docs.cypress.io/api/commands/invoke#jQuery-method

注意点

invoke + type の文字列(文字数)になる

invoke + type で入力した文字列は invoketype で指定したテスト文字列の合成になります。最大文字数のテストでは、特に数え間違いに注意。

最大文字数のテスト文字列を用意して 、それを invoke で呼び、type で追加1文字を入れて制限オーバーのテストを書くと読みやすいと思います。

厳密には同じテストではない

ユーザのキー入力は 1文字ごとに onChange が発生するので、type の方がユーザーの入力をよく模倣していると言えます。

たとえば「全角文字の入力禁止」のテストなら、ユーザーが「あ」と打ち込んだ時点で警告がでたり、文字が取り除かれたりしますが、 invoke + type では、最後まで入力したあとに、その処理が行われたような挙動に見えます。

通常は、その差異が問題にならないということです。

Gaji-Laboでは、React経験が豊富なフロントエンドエンジニアを募集しています

弊社ではReactの知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違うGaji-Laboを味わいに来ませんか?

もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!

求人応募してみる!