3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Cypressでユーザーエージェント(以降、UAと記載)による条件分岐のテストを行う場合、
E2EテストであればuserAgentの設定がありますが、
Componentテストの場合は上記の設定は効かず、
どのようにテストを書くのか非常に困ったのでまとめます。

いきなり結論

__defineGetter__window.navigatoruserAgentを直接書き換えることで解決できます。

test.cy.jsx
import Target from './Component'

before(() => {
    cy.mount(
        <Target>
            <div data-cy="children">test</div>
        </Target>
    )

    const chromeUA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
    // UAをchrome用の値に変更
    window.navigator.__defineGetter__(
        'userAgent',
        () => chromeUA,
    )
})
it('chromeの場合、childrenのみ表示すること', () => {
    // エラーメッセージが表示されないこと
    cy.get('[data-cy="エラーメッセージ"]')
        .should('not.be.exist')

    // childrenが表示されること
    cy.get('[data-cy="children"]').should('be.visible')
})

以降はそれなりに細かく解説を書いてきます。

対象読者

  • CypressでComponentテストを書いている人
  • UAの分岐処理をテストしたい人

コンポーネントの実装はReactで書きますが、
テスト自体はCypressで動かすため、テストの作成以降はVueなどでも問題ないはず。

実行環境

本記事は、以下の環境で実行を行いました。

  • macOS - Ventura
  • Node - 18.9.0
  • Vite - 4.3.8
  • React - 18.2.0
  • Cypress - 12.12.0
  • Safari - 16.5
  • Chrome - 114.0.5735.90

事前準備

Cypress等のセットアップはすでに完了している前提で進めます。

UAからブラウザを判断する処理をイチから書くのは骨が折れるので、
今回はUAParser.jsを使います。

UAParser.jsのインストール

npm i ua-parser-js

Safariの場合エラーを出すコンポーネントの作成

UAParser.jsが返すブラウザ名はここに定義されています。

今回はSafariの利用を制限する想定で、
browser.nameSafariを含む場合に分岐するよう処理を書いています。

Component.jsx
import { useState, useEffect } from 'react'
import { UAParser } from 'ua-parser-js'

const SafariError = () =>  (
    <p data-cy='エラーメッセージ'>
        Safariでのアクセスは禁止されています。
    </p>
)

export default ({ children }) => {
    const [isSafari, setIsSafari] = useState()

    useEffect(() => {
        // ブラウザのUAを取得
        const ua = window.navigator.userAgent
        // UAParseに渡してUAを扱いやすいように整形する
        const { browser } = UAParser(ua)
        // Safari、Mobile Safariのときtrueにする
        const isSafariBrowser = browser.name.includes('Safari')
        setIsSafari(isSafariBrowser)
    }, [])
    
    // まだ定義が無いの場合は何も返さない
    if (isSafari === undefined) return
    // trueになった場合は、エラーメッセージを表示する
    if (isSafari) return <SafariError />
    // falseになった場合は、そのままchildrenを表示する
    else return children
}

テストの作成

ブラウザからUAを取得する

UA変更は文字列で全文を指定する必要があるため、ブラウザからUAを取得します。

Chromeの場合

DevTools(F12)のConsoleタブでwindow.navigator.userAgentを入力してEnter

UA取得_chromeの場合.png

今回、私の環境で取得したUAは以下となります。
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36

Safariの場合

手順はChromeの場合と殆同じです。
Webインスペクター(⌥ + ⌘ + c)のConsoleタブでwindow.navigator.userAgentを入力してEnter

UA取得_safariの場合.png

今回、私の環境で取得したUAは以下となります。
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15

テストにUA書き換え処理を追加する

冒頭にも書いた通り、UAの書き換えは__defineGetter__window.navigatoruserAgentを変更することで実現できます。

beforeにUA書き換え処理を記載する

itの中に書くとUA書き換え前の状態でテストが行われるようなので、
beforeやbeforeEachの中にUA書き換え処理を書いていきます。

Component.cy.jsx
before(() => {
    // 実際のブラウザから取得したUA
    const chromeUA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
    // UAをchrome用の値に変更する
    window.navigator.__defineGetter__(
        'userAgent',
        () => chromeUA,
    )
})

mountとかitとか書いてく

mountのあとは、React以外のComponentテストで共通だと思います。

Component.cy.jsx
describe('Chromeの場合', () => {
    before(() => {
        // 実際のブラウザから取得したUA
        const chromeUA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
        // UAをChrome用の値に変更する
        window.navigator.__defineGetter__(
            'userAgent',
            () => chromeUA,
        )
    })
    it('childrenのみ表示されること', () => {
        // エラーメッセージが表示されないこと
        cy.get('[data-cy="エラーメッセージ"]').should('not.be.exist')

        // childrenが表示されること
        cy.get('[data-cy="children"]').should('be.visible')
    })
})

describe('Safariの場合', () => {
    before(() => {
        // 実際のブラウザから取得したUA
        const safariUA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15'
        // UAをSafari用の値に変更する
        window.navigator.__defineGetter__(
            'userAgent',
            () => safariUA,
        )
    })
    it('エラーメッセージのみ表示されること', () => {
        // エラーメッセージが表示されること
        cy.get('[data-cy="エラーメッセージ"]').should('be.visible')

        // childrenが表示されないこと
        cy.get('[data-cy="children"]').should('not.be.exist')
    })
})

実行結果

早すぎて見えませんが、UAごとの表示分岐をテストすることができました。
move.gif

トレタでは一緒に働く自動化エンジニア募集しています!!

トレタでは、テスト自動化エンジニア/SETの方を募集しています。
カジュアル面談もしていますので、興味のあるかたは是非ご応募ください!

他の業種も募集してます!

3
0
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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?