🎭

[Playwright]storageStateの読み込みがうまくいってるか確認する

2022/12/25に公開
  1. global-setupでログイン処理
  2. ログイン状態をstorageStateに保存
  3. テストを実行する前に読み込み
  4. テスト実行

という処理がどこかでうまくいっていないようで、
切り分けのためにどの時点でstorageStateの読み込みが確認できるのか調べてみました。

準備

セッションIDがCookieにセットされて、それをstorageStateに保存して読み込めるか確認したいので、以下を準備します。

  • set-cookieしてくれるサーバー
  • PlaywrightとglobalSetup
  • テストケース

1. set-cookieしてくれるサーバーを準備

express,express-sessionを使って作ってみます。

dockerでnode:latestのイメージを取得して、VSCodeのDev Containersで作業しました。

$ node -v
v19.3.0

$ npm init -y
$ npm install --save express
$ npm install --save express-session

app.jsファイルを作って以下のようにサーバーを作ります。

app.js
const express = require('express')
const session = require('express-session')
const app = express()

app.use(session({
    secret: 'kanikuriimukorokke',
    cookie: { maxAge: 60000 },
    resave: false,
    saveUninitialized: true,
}))

app.get('/',(req,res) => {
    req.session.count = req.session.count ? req.session.count + 1 : 1;
    res.send('<p id="count">count: ' + req.session.count + '</p>')
})

app.listen('3000',() => {
    console.log('Server running at http://127.0.0.1:8000/')
})

起動してみます。

$ node app.js

ブラウザでhttp://localhost:3000/にアクセスするとcount: 1と表示されるはずです。
chromeで検証 > アプリケーション > Cookie > http://localhost:3000/ を確認するとconnect.sidにセッションIDらしきものが入っていることが確認できます。

ページをリロードすると画面の表示がviews: 2になり、connect.sidは変化していないことを確認できます。

2. playwrightとグローバルセットアップを準備する

こちらは上記のdocker環境と要件が合わずブラウザのインストールができなかったのでローカルで実施してます

$ npm init playwright@latest

$ node -v
v18.12.1

$ npx playwright --version
Version 1.29.1

global-setupファイルを作成

global-setup.ts
import { chromium, FullConfig } from '@playwright/test';

async function globalSetup(config: FullConfig) {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('http://localhost:3000/');
  await page.context().storageState({ path: 'storageState.json' });
  await browser.close();
}

export default globalSetup;

playwright.config.tsにglobalSetupを追加
ついでにprojectをchromeだけにしておきます。

playwright.config.ts
const config: PlaywrightTestConfig = {
  ...
  globalSetup: require.resolve('./global-setup'),
  ...
}

3. テストケースの準備

テストファイルを追加

/tests/session.spec.ts
import { test, expect } from '@playwright/test'

// これでテスト実行時にブラウザに同じcookieがセットされる
test.use({ storageState: 'storageState.json' })

test('同じセッションIDでアクセスできてるか', async ({page}) => {
    await page.goto('http://localhost:3000/')
    // ↓2回目のアクセスなのでcount: 2のはず
    await expect(page.locator('#count')).toHaveText("count: 2")
})

実行してみる。成功しました。

$ npx playwright test
Running 1 test using 1 worker

  1 passed (1s)

To open last HTML report run:

  npx playwright show-report

cookieがどの時点で取得できるか調べる

--debugしてみる

$ npx playwright test --debug

テストケースの await page.goto('http://localhost:3000/');の実行前で止まっているので
この時点でcookieを見てみると、セットされていないみたいです。

なんとなくブラウザ立ち上がった時点で読み込まれてるのかなと思ってたんですがそうではないみたいですね。

1つステップオーバーしてもう一度確認してみます。
セットされてました。

countも2になってるのでpage.goto()が実行される前にセットされるみたいです。

普通にデバッグしてると、最初の時点でcookieがセットされていないから「storageStateの読み込み上手くいってなさそう」って勘違いしてしまいそうです...。

traceを見てみる

configでtraceをonにします。

playwright.config.ts
const config: PlaywrightTestConfig = {
  ...
  use: {
    ...
    trace: 'on',
    ...
  },
}
$ npx playwright test
$ npx playwright show-report

htmlレポートでテストケースを開いて下の方にあるtracesをクリックします。
cookie関連を確認できる項目はなく、見れないみたいですね...。

browserContext.cookies()で確認してみる

BrowserContext | Playwrightこれで確認してみます。

tests/session.spec.ts
... 
test('同じセッションIDでアクセスできてるか', async ({page}) => {
    // 先頭でcookieを取得してconsole.log()する
    const cookie = await page.context().cookies('http://localhost:3000/')
    console.log(cookie)
    await page.goto('http://localhost:3000/')
    await expect(page.locator('#count')).toHaveText("count: 2")
})
$ npx playwright test
Running 1 test using 1 worker
[chromium] › session.spec.ts:5:5 › 同じセッションIDでアクセスできてるか
[
  {
    name: 'connect.sid',
    value: 's%3Au7U67oWuIyxC_1bZFensbtkx-eHD4Lgu.kvyLufTuhV%2B675beYGe2TmhDtLhObu%2BMp7BijfoRfKs',
    domain: 'localhost',
    path: '/',
    expires: 1671958463.919827,
    httpOnly: true,
    secure: false,
    sameSite: 'Lax'
  }
]

  1 passed (1s)
  ...

取得できてますね!

結論

test.use({ storageState: 'storageState.json' })が上手くいってるか確認するには、
テストの先頭にpage.context().cookies()で中身を確認するのが手っ取り早くて確実そうです。
--debugだと最初に確認できないので若干疑いの余地が残ります…。

Discussion