20210315のHTMLに関する記事は9件です。

下線アニメをbackground-sizeのanimationで実装したらIE11で動かなかったけど切り捨てた

はじめに

「元々リンクテキストに下線が引いてあって、マウスホバーするとその下線が左から右へアニメーションする。」

そんなあるある要件を満たすためにいろいろと試してみました、が、悪しからず、完璧なIE11対応はできなかったので諦めました、という残念な記事です。

ぜひ、ナレッジがある方はお知恵を拝借できれば幸いです。

追記(2021/03/16): お知恵を頂き、追記しました。

実際にやってみた

ベースとなるHTMLは以下の通りです。

HTML
<a>リンクテキスト<br>2行目です</a>

まずはscale()で実装

widthを使ったりいろいろ実装方法はあると思いますが、まず私はtransform: scaleX()で実装しました。
transform-originを変えればアニメーションの起点を簡単に真ん中にしたり右端にしたり変えられると考えたからです。

Mark.I(疑似要素で実現)
a {
  position: relative;
  display: inline-block;
  text-decoration: none;
}
a::after {
  position: absolute;
  bottom: 0;
  left: 0;
  content: "";
  width: 100%;
  height: 1px;
  background: #000;
  transform: scaleX(1);
  transform-origin: left top;
}
a:hover::after {
  animation: leftToRightUnderline 0.3s;
}

@keyframes leftToRightUnderline {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

See the Pen LeftToRight Mark.1 by heeroo-ymsw (@heeroo-ymsw) on CodePen.

疑似要素afterで高さ1pxの線を作ってテキストの下に配置し、左端を起点にanimationで要素を拡大させています。
今回はもともと下線が引いてあるので、マウスホバーを外したときのアニメーションはありません。

しかし、このコードには問題があり、テキストが2行以上になるとそのブロックの下に下線がひかれ、「テキストの下線」ではなくなってしまいます。

複数行にも対応させる

Mark.II(複数行対応版)
a {
  background: linear-gradient(#000, #000) 0 bottom/100% 1px no-repeat;
  text-decoration: none;
}

a:hover {
  animation: leftToRightUnderline 0.3s;
}

@keyframes leftToRightUnderline {
  from {
    background-size: 0% 1px;
  }
  to {
    background-size: 100% 1px;
  }
}

See the Pen LeftToRight Mark.2 by heeroo-ymsw (@heeroo-ymsw) on CodePen.

疑似要素を用いるよりもスッキリした印象です。

linear-gradient()background-sizeで幅100%/高さ1pxの下線を書いておき、background-sizeをアニメーションさせることで実現しています。

しかし、こちらにも問題点が。

IE11はbackground-sizeのtransition/animationに対応していません。

r_655811_6dC5m.gif

IE11に対応させる

Mark.III(IE11対応)
a {
  background: linear-gradient(#000, #000) 0 bottom/100% 1px no-repeat;
  text-decoration: none;
}
a:hover {
  animation: leftToRightUnderline 0.3s;
}

@keyframes leftToRightUnderline {
  from {
    background-position: -190px bottom;
  }
  to {
    background-position: 0 bottom;
  }
}

See the Pen LeftToRight Mark.3 by heeroo-ymsw (@heeroo-ymsw) on CodePen.

background-positionで左にずらしとくパターンです。
ただし、これも残念ながら万能策ではありません。
むしろ、問題が増えました

  • 下線を適応させたい要素に応じて、ずらし具合(例だと-190pxの部分)を調整しなくてはいけない
  • ずらし具合の調整が地味に面倒
  • アニメーション方向が変わった場合などの汎用性が低い

そのうちコーダーは考えるのをやめた

今回は以下の言い訳とともにIE11を切り捨てbackground-sizeで実装しました。

  • 調べたらpolyfillもあったが、案件でそれを検証している時間がない
  • background-positionを使っても、実装当初はリンクが増える、もしくはテキストが変更になる可能性が大いにあり、その度にズレを調整していられない
    • ついでにレスポンシブ対応&PCサイズのときはリキッド対応の必要がある

そして、賢者が現れる

2021/03/16 追記

この記事を出したところ、賢者から知恵を頂くことができたので、改めてこの問題に向き合いました。
非常に勉強になります。ありがとうございます。

MarkIV(IE11対応&汎用性UP)
a {
  background: linear-gradient(to right, #000 50%, transparent 50%) 0 bottom/200% 1px no-repeat;
  text-decoration: none;
}
a:hover {
  animation: leftToRightUnderline 0.3s;
}

@keyframes leftToRightUnderline {
  from {
    background-position: 100% bottom;
  }
  to {
    background-position: 0% bottom;
  }
}

See the Pen LeftToRight Mark.4 by heeroo-ymsw (@heeroo-ymsw) on CodePen.

端的に言えば、linear-gradient()で横方向のグラデーションを作成し、それをbackground-positionで左右に動かすというものになります。

■□←こんな感じのグラデーションを作って、横を2倍に引き伸ばして、background-positionは左端に寄せておいて下線を常時表示します。
アニメーション時は、background-positionを右端に寄せて左端へ動かすことで左から右へ下線が動くように見えます。なるほどすごい!

しかしながら、はたまた問題が

IE11だとkeyframesでアニメーションしない……

transitionだと動くのですが、下線を元々表示したい関係でkeyframesを使っており、これが動きませんでした。
書き方が悪いのか、IE11の仕様なのか…現在調査中です。

まとめ

テキストの下線アニメーションの実装を行い、現段階では、background-sizeのanimation / transitionでの実装が最適解かと感じました。

background-positionの代替案が出来たと思ったのですが、keyframesによるanimationがうまくいきませんでした。謎。
鋭意調査続行中であります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

cssでの優先度〜class属性、id属性〜

①class属性

クラスとは、簡単に言うと学校のクラス学級のようなもので、何年何組みたいなものです。
またこのclass名は1ページで何度でも使うことができます。
こちらは、要素に対しての指定として使われます。
例えば、ヘッダーとしての要素があるとします。その際class="header"と使われます?

②id属性

反対にid属性は1ページで1回のみ使うことができます。
こちらは
固有の名前を付ける場合に使われます?
class属性とは違いこちらは、出席番号のようなものです。
同じクラスの同じ人が何人もいるわけにいきませんよね(・・;) 

またこれらは、cssを適用する場合にも影響があります。

cssでは、class属性よりもid属性が強い関係にあります。

では、cssでの優先度について考えてみましょう。

cssには記述方法が3つほどあります。

①HTMLタグ

こちらはHTMLタグの中に書く方法です。

index.html
<p style="color:aqua">マイメロディ</p>

外部に書くのが基本なのであまり使われませんが、このような書き方も可能です。

②head内に書く

こちらは、HTMLのヘッド内に書くことによって、このページではこのタグはすべてこのようにしてくださいと指定することができます。

index.html
<style type="text/css">
  p {color: pink;}
  </style>
  <title>Document</title>
</head>
<body>
  <p>お願い</p>
  <p>マイメロディ</p>
</body>

と書くことにより、このページでpタグが出てきた場合はすべてピンクになります?♡

③cssの外部ファイルに書く

これは一番ベストなので説明する必要もありませんが、cssno
記述の場合、上から順番に読み込まれていき、一番優先されるのは下にある要素だと学習しましたね。

上記の中で一番優先的に反映されるのは、個別的に当てているHTMLタグの中に当てているcssです。

☆まとめ☆
1.class属性とid属性でcssの強制力が変わる
2.cssを書く場所により強制力が変わる

でした!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CSS~!important~

CSSには優先度というものがあります。
上から書いたものが、下に向かって反映されていきます。

例えば、このように記入したとしましょう。

index.html
<h1>今日は何をしていましたか??</h1>
style.css
h1 {
  color: red;
}

h1 {
  color:blue;
}

この場合、優先的に反映されるのは一番最後に記入されたcssになります。
スクリーンショット 2021-03-15 17.05.19.png

こうなりますね。
赤色を反映したいとしましょう。
ここで使うのが、『!important』です。
では先程のcssに付け加えていきます。

style.css
h1 {
  color: red !important;
}

h1 {
  color:blue;
}

とすると、赤色が反映されました。
スクリーンショット 2021-03-15 17.09.04.png

ただし、このタグは本当に優先したいものに付けるようにしましょう!
使わないのがマストです?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ベーシック認証の付け方

ベーシック認証作業忘れないように、備忘録_φ(・-・

-----------------

①.htaccessファイルを作成し、以下を追記(既にあれば追記)

AuthType Basic
AuthName "Please enter your ID and password"
AuthUserFile "フルパス\.htpasswd"
require valid-user
 //←改行一行入れる

②.htpasswdファイルを作成
▼ココでID/PWを作成(オススメ)
https://www.en-pc.jp/tech/htpasswd.php#htpasswd
※パスワードは8文字以内がオススメ(長すぎると通らない可能性大)
※暗号化方式を「MD5」に(それ以外は通らない可能性大)

③生成されたパスを.htpasswdファイルに追記

④シークレットウィンドウで確認する

◎リリース時は.htaccessから、追記した行を消すのを忘れない!!

-----------------

いつもベーシック認証の仕方忘れて鳥頭になるので、私的備忘録です。
今回は.htpasswd作成で詰みました。
回避方法は暗号化方式をMD5にしたらいけたけど、、パスワード5文字以内にしたのにCRYPTで通んなかったのなんで…??:rolling_eyes:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ベーシック認証の付け方【初心者】

【初心者向け】ベーシック認証作業忘れないように、備忘録_φ(・-・

-----------------

①.htaccessファイルを作成し、以下を追記(既にあれば追記)

AuthType Basic
AuthName "Please enter your ID and password"
AuthUserFile "フルパス\.htpasswd"
require valid-user
 //←改行一行入れる

②.htpasswdファイルを作成
▼ココでID/PWを作成(オススメ)
https://www.en-pc.jp/tech/htpasswd.php#htpasswd
※パスワードは8文字以内がオススメ(長すぎると通らない可能性大)
※暗号化方式を「MD5」に(それ以外は通らない可能性大)

③生成されたパスを.htpasswdファイルに追記

④シークレットウィンドウで確認する

◎リリース時は.htaccessから、追記した行を消すのを忘れない!!

-----------------

いつもベーシック認証の仕方忘れて鳥頭になるので、私的備忘録です。
今回は.htpasswd作成で詰みました。
回避方法は暗号化方式をMD5にしたらいけたけど、、パスワード5文字以内にしたのにCRYPTで通んなかったのなんで…??:rolling_eyes:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

動画下の余白を消したい!

症状

videoタグで動画を表示する時に、
動画の下に余白が生まれることがあります。

「そんな余白を消したい!!」

という時の対処法です。

対処法

  1. videoタグの親要素にline-height: 100%;を指定
  2. videoタグの親要素にdisplay:flex;align-items: end;を指定

1の方法は下記の記事から引用させていただきました。
動画に謎の余白やマージン!削除する方法(HTML / CSS)
こちらの方法で問題なければバンザイです。
2へ進む必要はありません。

ただ、私の場合、
こちらの方法でも多少余白が少なくなったのですが、
少しだけ余白が残ってしまいました。

そこで、2の方法を試してみました。
すると、余白がきれいに無くなりました。

よかった。

備忘録なので簡単にしか説明していませんが、お困りのかたのお力になれれば!
以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTMLによる動画のダウンロード禁止について

最初に

WEBサーバで動画を配信したいが、ダウンロードはさせたくないという要件
を満たすには。

HTML5のvideoタグによる制御とapacheの設定で実現できたので共有。

調べれば個別に検索に引っ掛りますが、まとまったのがなかったので

HTMLによる制御

videoタグに下記オプションを追加する。

oncontextmenu="return false; ※右クリックからのダウンロードを禁止
controlsList="nodownload" ※ダウンロードオプションを非表示

 <video src="video/test.mp4" oncontextmenu="return false;" controls controlsList="nodownload" preload="auto" width="100%" height="100%"></video>

apacheの設定

直接アクセスを禁止させたいフォルダのパスを記述
これでHTMLによる制御と、直接アクセスによるダウンロードを阻止する。

<directory [アクセス禁止フォルダパス]> ※/var/www/html/videoなど
 Require all denied
</Directory>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Webフォント】日本語Webフォントがすぐに表示されない場合の対処法

はじめに

私たちが普段見ている様々なサイトでデザイン性を高めるために「Webフォント」が使用されています。
Webフォントを使用するメリットはたくさんあり、「どのブラウザで見ても同じ表示になる」「文字を画像で表示しないためSEOの効果を維持できる」などがあげられます。
しかし、メリットの反面デメリットもあります。WEBフォントの読み込みが遅く、最悪の場合「サイトが表示されてから数秒の間文字が表示されない」なんていう事象が発生する可能性があるのです。
特に日本語は漢字・ひらがな・カタカナと英語圏のアルファベットに比べると桁違いに文字が多いため、フォントデータのサイズも大きくなってしまいます。
今回はWebフォントのメリットを享受しつつデメリットを打ち消す方法を紹介します。
※一般的な方法なので「そんなの当たり前じゃん」と思う方もいると思いますがご了承ください。

確認方法

「目視だとわからない・・・。」という方はGoogleのPageSpeed Insight(ページスピードイン)等のパフォーマンス測定サイトで確認してください。
※PageSpeed Insightの使用方法は割愛します。

以下のような表示になる場合は「サイトが表示されてから数秒の間文字が表示されない」可能性があります。
1.png

対処方法

「Webフォントが読み込まれるまで、とりあえず通常のフォントで文字を表示させておく」という設定をします。
基本的に「font-display: swap;」の指定をするだけで完了です。
では具体的に説明します。

1.一般的なWebフォントの場合

font-face内に「font-display: swap;」の指定をするだけです。
※下記コードの一番下

@font-face {
  font-family: 'hogefont';
  font-style: normal;
  font-weight: 400;
  src: url(https://fonts.hoge.com/hoge/hoge/hoge.woff2) format('woff2');
  font-display: swap;
}

2.Googleフォントを使っている場合

Googleフォント(Google Fonts)はGoogleが提供しているWebフォントサービスです。
すべて無料で利用可能で、かつ商用利用にも対応しています。日本語フォントも豊富なため、Webフォントを利用する方はまずGoogleフォントを選択肢の一つに入れるのではないでしょうか。Googleフォントでの指定方法も紹介します。

Googleフォントを使っている場合は、埋め込みタグのURLに「&display=swap」を追加してください。

<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100&display=swap" rel="stylesheet">

デフォルトの埋め込みタグは下記図の赤枠のように「&display=swap」が付いた状態ですが、ブログ等で紹介されているタグには付いていないことも考えられるため注意してください。
3.png

再度パフォーマンス測定サイトで確認

対応後にパフォーマンス測定サイトで確認し、以下の表示になっていることを確認してください。
2.png

先程は赤い三角印だったものが緑の丸になっています。
※GoogleのPageSpeed Insightで確認しています。

これでWebフォントのメリットを享受しつつデメリットを打ち消すことが出来ました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

cypress で期待通りに自動テストが動かなかったときの対策集

Click point

前回の「cypress を使って自動テストを簡単に導入する方法」の続きです。

テストコードとブラウザーが非同期で動いていることに対応する機能とその限界

cypress など、ブラウザーを使って自動テストをする場合、
テストコードは、ブラウザーとタイミングを合わせながら非同期で動くのですが、
それが原因でテストコードが期待通りに動かないケースがよくあります。

010_async.png

たとえば、入力値を入れる GUI 部品が表示される前に入力しようとすると、
入力しないまま次のテストコードを実行してしまいます。
テストをすることは、入力した値に対して出力値が正しい値(期待する値)であることをチェックすることですから、
そもそも入力できなければ正しくテストを実行できません。

cypress では正しく入力できるように、対象の GUI 部品が表示されるまで自動的に待ってから
実行するように常に動いています。 たとえば cy.get メソッドが待ちますが、それ以外のメソッドでも待ちます。
フォームの項目に入力するときも入力が完了するまで待ちます。

通常、テストコードの実行はブラウザーがページをレンダリングする処理よりも速いため、
テストコードの内部では短い待ちが頻繁に発生しています。
しかし、この待ちを cy.get メソッドなどの内部で自動的に行っているおかげで、
テストコードに待ちを書く必要がなくなり、実施したいテストの仕様の記述に集中できるのです。

cy.get('#input-text')
    // ... <input id="input-text"/> がレンダリングされるまで待つ

しかし、表示されるまで自動的に待ったとしても、あらゆるケースで完全にタイミングが
合うとは限りません。

表示されるまで待つべきか、いつまでも表示されないのか

もし、cy.get メソッドに指定した ID が存在しない ID だったらどうなるでしょう。
HTML のレンダリングが完了しても対象の GUI部品は表示されずに待ち続け、
いずれタイムアウトのエラーになります。

ブラウザーから cypress に HTML のレンダリングが完了したことが通知されれば、
そのタイミングですぐに対象の GUI部品が見つからないというエラーにすることができるのですが、
そのような仕組みは無いようです。

よって、タイムアウトの原因は大きく分けて2つ考えられます。
- レンダリング中
- テストコードの実行に失敗した

ただし、これはタイムアウトの原因の一部にすぎません。

タイムアウトでエラーになる原因はいくつもある

cypress のタイムアウトの原因はいくつも考えられえます。

  • レンダリング中
  • 対象の GUI部品の指定が間違っている(対象の GUI部品が表示されるまで待っている)
  • 対象の GUI部品が非表示になっている
  • 入力しようとしている GUI部品が無効状態になっている
  • 対象の GUI部品が別の GUI部品の奥に隠れていて操作ができない
  • 対象の GUI部品がスクロールしないと見えない位置にある
  • マウスを合わせると(ホバリングすると)表示される要素が表示されない
  • 出力値を表示するまでに時間がかかっている
  • 誤った出力値が表示されている(期待する出力値が表示されるまで待っている)
  • 対象の GUI部品がアニメーションして動いているため、 クリックをブラウザーに要求してから実際にクリックされるまでの間に、 GUI 部品がクリックした位置から移動した
  • モーダル表示を閉じるアニメーションの途中でも、 閉じた後で操作する対象の GUI部品は表示されているため、 モーダル表示が閉じられる前に操作しようとして失敗した
  • タイムアウトしたところより前のテストコードの操作が失敗していたがスルーされていた

他にも原因があるかもしれませんが、今回これらが原因であるときの対処法を紹介します。
ただし、どれが原因であるかは、テストコードを実行したときのブラウザーの様子を目視で
確認して判断しなければなりません。その判断をした後での対処法になります。

レンダリング中のときや、出力値を表示するまでに時間がかかっているときの対処法

タイムアウトしたときにブラウザーのレンダリングや出力するまでの処理が完了していないようだったら、
タイムアウトの時間を延ばします。
特にページを移動するときにタイムアウトになる可能性が高いので、
ページの最初の GUI 部品を特定する cy.get メソッドに timeout オプションを指定します。
timeout オプションの値の単位はミリ秒です。

cy.get('#input-text', { timeout: 30000 }).should('have.value', 'ABC')

ただし、ページが表示されるまで待つコードのほうが可読性が高まります。
その場合、最後のほうでレンダリングする GUI 部品が表示されるまで待つコードを書きます。

cy.get('#last-button', { timeout: 30000 }).should('be.visible')

cypress の should メソッドは値のチェックだけではなく、
その状態になるまで待つという意味も含んでいると考えると読みやすくなります。
また、timeout オプションが書いてあると長時間待つ必要があるということも伝わります。

デフォルトのタイムアウトは 4秒ですが、
4秒では待っていないように見えるときでもタイムアウトになることが多いので 10秒にするとよいでしょう。
性能が悪い PC を使っているときは、もっと長くする必要があるかもしれません。

cypress.json

{
    "defaultCommandTimeout": 10000
}

参考: https://docs.cypress.io/guides/references/configuration.html#Timeouts

しかし、タイムアウトを長くしてもタイムアウトするまでにブラウザーに動きが全くなかったら、
タイムアウトの長さが原因ではないのでタイムアウトまでの時間を戻した方が素早く開発できます。

ちなみに、デバッグ対象の HTML のロードに時間がかかるときは、
ロードした HTML を cypress fiddle にコピーして実行すれば素早く
テストコードをデバッグできます。

cy.get に失敗するときや、対象の GUI部品の指定が間違っているときの対処法

cy.get に失敗するときは、
前回の「cypress を使って自動テストを簡単に導入する方法」で説明した Selector Playground
を使って typo を防ぎます。

ただし、

cy.get('#input-text')

または

cy.get('[data-test=input-text]')

のようなシンプルな cy.get ではないときは、前回説明したように、
id 属性または data- 属性(例:data-test 属性)を記述してください。

対象の GUI部品が非表示または無効状態になっているときの対処法

操作対象の GUI 部品が表示前または非表示または無効状態になっていると、
その GUI 部品は操作を受け付けません。
これは、手動でブラウザーを操作したときの仕様なのですが、
cypress でブラウザーを操作したときも同じです。

多くの場合、表示や有効状態にするための操作が正しく実行されなかったか、
テスト対象にバグがあることが原因です。

cypress は、対象の GUI 部品が非表示または無効状態のときは、
有効状態に変わるまで待ち続けます。
ビジー状態で各種 GUI 部品を無効状態にしているアプリケーションのときは、
無効状態ではなくなるまで自動的に待ちます。

テストコードに表示や有効状態であることを事前にチェックするコードを書く必要はありません。
次のようなコードではなく、

cy.get('#input-text').should('not.be.disabled')
cy.get('#input-text').clear().type('ABC')

次のようなコードを書きます。

cy.get('#input-text').clear().type('ABC')

同様に表示状態であることをテストコードに書く必要はありません。

cy.get('#input-text').should('be.visible')
cy.get('#input-text').clear().type('ABC')

表示状態になるまでの時間が長いときは、レンダリング中のときの対処法を参照してください。

別の GUI部品の奥に隠れているとき、スクロールしないと見えない位置にあるときの対処法

cypress でブラウザーを操作すると手動で操作したときで、
レイアウトやスクロール位置が異なることがあります。

ブラウザーの中のページのサイズを調整することで対象の GUI 部品が隠れないようにできるのであれば、
前回の「cypress を使って自動テストを簡単に導入する方法」で説明したように、
cypress.json の viewportWidth と viewportHeight を編集します。

常に手前に表示されるツールバーに隠れてしまい、スクロールすれば隠れないようにできるときは、

cy.get('[data-test=middle-button]').scrollIntoView()

の cy.get の対象となる GUI 部品の選択を工夫してスクロールさせます。

もしくは、force: true オプションで隠れた GUI 部品を強制クリックします。
ただし、奥に隠れている GUI 部品を操作することはできないという不具合は
検出できなくなるのであまりお勧めできません。

cy.get('[data-test=button]').click({ force: true })

マウスを合わせると表示される要素が表示されないときの対処法

cypress はマウスを動かしてホバリングすることをエミュレーションすることができません。

force: true オプションで表示されない GUI 部品をクリックします。

cy.get('[data-test=button]').click({ force: true })

誤った出力値が表示されている

おそらくテスト対象にバグがあります。
前回の「cypress を使って自動テストを簡単に導入する方法」で説明したデバッグ表示の方法を
使ってデバッグしてください。

ただし、後述するように、タイムアウトしたところより前のテストコードの操作が失敗していた
可能性もあるので注意してください。

対象の GUI部品がアニメーションして動いているときの対処法

cypress から起動したブラウザーの左半分に表示されるログの中にある click メソッドに
マウス カーソル を合わせると、クリックした位置が赤い丸で表示されるのですが、
クリックする対象となる GUI 部品がアニメーションして動いていると、
クリックした位置がずれて失敗することがあります。
Bootstrap のモーダル表示など表示を開始するときにアニメーションさせるとこの問題が発生します。

Click point

下記の waitForAnimation 関数を呼び出して、アニメーションが止まるまで待つことで、
クリックする位置がずれる問題に対処できます。

// waitForAnimation
// Example: waitForAnimation('[data-test="user-mail-address"]')
export function  waitForAnimation( getParameter ) {
    cy.get(getParameter).should('be.visible')
    cy.get(getParameter).then( (elements) => {
        const  element = elements[0];
        let    old = element.getBoundingClientRect();
        for (var i = 0; i < 10; i++) {
            cy.wait(100);
            const  new_ = element.getBoundingClientRect();
            if ( old.x !== new_.x  ||  old.x !== new_.y ) {
                break;
            }
            old = new_;
        }
        cy.wait(100);
    })
}

モーダル表示をアニメーションしながら閉じた直後の操作が失敗するときの対処法

これも Bootstrap などによってモーダルを閉じるアニメーションをするときによく発生する問題です。

対処するには、モーダル表示に含まれる GUI 部品が完全に非表示になるまで待ちます。

cy.get('[data-test=button]').should('be.not.visible')

HTML のイベントが発生しないときの対処法

<input onChange="onChange(event);"/>

の onChange のように on から始まるイベント属性や addEventListener メソッドで登録した
イベント ハンドラー が実行されないときは、
.trigger メソッドの呼び出しを書くと実行されます。
.trigger メソッドに指定するイベントの名前の先頭には on が付かないことに注意してください。

cmd.uploadFile( cy.get('[data-test="file-selector"]'), '申請書.docx')
cy.get('[data-test="file-selector"]').trigger('change')

参考: https://github.com/cypress-io/cypress/issues/1570

タイムアウトしたところより前のテストコードの操作が失敗していたときの対処法

テストコードが止まったところよりも前に原因があることは非常によくあります。

たとえば、入力値の設定が行われていなかったら、
出力値が誤った値になり、出力値をチェックするコードでタイムアウトになります。
よって、出力値が誤っていたからテスト対象のコードに不具合があると決めつける前に、
入力値が正しく入力されているかを目視でチェックしなければなりません。

他にも、対象のボタンが押せない原因は、対象のボタンが無効状態から有効状態に変えるための
別の GUI 部品の操作に失敗していたからかもしれません。
テスト対象が無効状態になっているのはバグだと決めつける前に
別の GUI 部品の操作が正しく実行されたことを目視でチェックしなければなりません。
この場合も、テストコードが止まったところよりも前に原因があります。

cypress はテストコードが止まったところよりも前の画面の様子を遡って確認することができます。
自動テストは操作が素早いのでじっくり見ることが難しいのですが、
cypress から起動したブラウザーの左半分にあるログにマウスカーソルを合わせると、
ログに表示されているテストコードを実行した瞬間にブラウザーに表示された様子が
右半分に表示されるためじっくり確認することができます。

cy.get にマウスカーソルを合わせると、cy.get に成功した GUI 部品が強調表示されます。

Click point

テストコードが正しく動いていることを確認したら、テスト対象のデバッグやバグ報告をしましょう。

その他、どうしてもタイミングが合わせられないときの対処法

待ちが終了するタイミングの条件がどうしても分からないときは、
一定時間待つことで動くようになるかもしれません。

cy.wait(500)  // Wait for 500 msec

ただし、一定時間待ってタイミングを合わせる方法は、
次回のテストで失敗する可能性があるため、あまりお勧めしません。

cy.wait を追加した今回は早くテストが通るようになりますが、
テストの実行時間が長くなってしまうことと、
後で時々動かなかくなったときに多くの時間が取られる可能性が高いです。
タイムアウトとは異なり、必ず指定した時間だけ待つため、
待つ時間を短くしたいという圧力もかかり失敗する可能性が高まります。
できるだけ cy.wait を使わないで済むパターンを学んでおくべきです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む