LoginSignup
5
5

More than 1 year has passed since last update.

CypressでCognitoにログインするテストケースを通すのに苦労したポイント

Last updated at Posted at 2021-03-18

概要

  • cypressを初めて使う筆者が
  • cognitoを認証基盤に利用するwebアプリに
  • ログインするテストケースを作った際にハマったポイントまとめ

先に結論

ここのコードに解決策が全部入ってるからこれ見ればok
https://gist.github.com/vittorio-nardone/a9b388ff7388a4ae7343cd6a2758bc4b

背景

最初、cypressをcognitoに使った事例探したらクラメソさんの記事があって、
https://dev.classmethod.jp/articles/amplify-console-cypress/

助かったー、と思いつつ参考にして実践してみたがだめだったので、色々と試行錯誤した軌跡

ハマったポイント

セレクタで入力フォームを取得できない

ログイン画面を表示させて、inputタグに入力すべくセレクタで指定したが、見つからないエラー

describe("Login Test", () => {
  it('Shows Login', () => 
    cy.visit('https://xxxx/login')
    cy.get('[data-test="sign-in-username-input"]')
  })
}

これを実行すると、見つかりません、と言われます。

cypress_error_selector.png

Timed out retrying after 4000ms: Expected to find element: [data-test="sign-in-username-input"], but never found it.

入力フォームのタグを確認したら data-test="sign-in-username-input" 要素は間違いなくある

<input id="username" type="text" placeholder="xxx" class="input" data-test="sign-in-username-input">

なのになぜ?

iframeの影響か?いや使ってないな、とか
タグが深くなったら届かない?とか
amplify-sign-in タグまで辿れてその先の amplify-form-section が辿れないのなんでやとか
色々調べましたが、解決には至らない

キレてる。怖い。

解決策

cypressのgetにオプション { includeShadowDom: true } をつけて解決しました。

cy.get('[data-test="sign-in-username-input"]', { includeShadowDom: true })

参考) https://docs.cypress.io/api/commands/get.html#Arguments

原因

コンソールログを見ると #shadow-root(open) って表記があります。
cypress_console.png

なんそれ

shadow DOM

コンポーネントっぽくDOMを利用できるっぽいなにからしい(かなり浅い理解
まあ、なんせshadowって言ってるぐらいなんで、隠れてるんでしょうね。なので、セレクタが見つけれなかったと。
で、それでも見つけてくれるオプション includeShadowDom ができたと。

デフォルト true じゃあかん?
と思ったら、configurationにあるので変えれそう

パスワード入力フォームにtypeできない

ログインIDはセレクタで取得しtypeで入力できたので、次パスワード、と意気込むとこのエラーがでました。
cypress_password_error.png

cy.type() failed because it targeted a disabled element.
  > <input id="password" type="password" placeholder="パスワード" class="input" data-test="sign-in-password-input">
Ensure the element does not have an attribute named disabled before typing into it.

なんか途中のinputタグの表現がキレてる。今度は私じゃなくてタグがキレてる。怖い。

エラー文にあるような、 disabled な要素になってないのは確認した。
で、ググってみると同様の現象はあるようで、以下のように解決してた。

    cy.get('[slot="sign-in"]').find('#password', { includeShadowDom: true }).click({force: true})
    cy.get('[slot="sign-in"]').find('#password', { includeShadowDom: true }).type('password')

一回 .click({force: true}) で強制クリックでフォーカスしておいて type() すると。なるほど。
これで動作した。

が、結論にのせたgistにもっとスマートな方法があった

    cy.get('[slot="sign-in"]').find('#password',{ includeShadowDom: true } ).type('password', {log: false, force: true})

type() に force:true optionあるやん。1行ですむやん。素敵やん。

ローカル環境でAPIリクエストが502 Bad Gateway

これらをクリアし、いざログインしてみると、
なぜかAPIリクエストのレスポンスが502 Bad Gateway で返ってくる。ちなみに以下のような構成。

cypress_local_dev_env.png

  • AWS上の開発環境だと問題なかった
  • Cognitoから返ってきてるIdTokenの中身をdecodeしてみたが、開発環境とほぼ変わらず問題なさそうに見えた

もちろん、素のchromeだと期待通り動作する。
なので、違うのはブラウザの違いぐらいかな、とか思いながらまだ未解決

追記)解決した

原因

認可処理で、アプリケーション(lambda) で受け取る変数 event.header.Authorization が、
cypress上のブラウザからのリクエストだと event.header.authorization になってた。

cypressが投げるリクエストヘッダは Authorization なので、何故、誰が小文字にしたのかは謎。

ServerlessFrameworkをローカルで動かすプラグインservlerless framework offlineのせいかな・・・?

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5