/** * ログアウトの道具(issue #1484)。 * * ログイン直後の画面は、個人ワークスペースを自動で開くために * `GET /api/local/spaces/:id/tool-policy` を投げる。これは一覧 * (`GET /api/local/spaces`)が返ってから始まる 2 往復目なので、テストが * 次の利用者へ切り替えようとする頃にちょうど飛んでいることがある。 * * ここで `/auth/logout` へそのまま移ると、次の順序が起こりうる。 * * 1. 画面が tool-policy を投げる(この時点ではまだログイン済み) * 2. サーバが `/auth/logout` を処理し、セッションを壊す * 3. tool-policy に 401 が返る * 4. `/auth/login` の表示が始まり、古い画面がようやく捨てられる * * 3 と 4 の間はわずか数ミリ秒だが、その間だけ**古い画面は生きたまま 401 を * 受け取る**。spec が仕掛けた `page.on('response')` はそれを拾い、赤になる。 * コードを変えずに回し直すと緑になるのはこのためで、CI の走り 3312 が実際に * これで落ちた(3313 は同じコードで緑)。 * * 直し方は待ち時間を足すことではない。**合図を消す前に画面を畳む**—— * `about:blank` へ移せば画面の JavaScript はそこで止まり、セッションが死んで * いる間に要求を出せる主体がいなくなる。競争そのものが無くなる。 * * 逆順(先にログアウト、あとで画面を畳む)に戻すと、この 401 は再び起こる。 */ import type { Page } from '@playwright/test'; export async function logout(page: Page) { // 先に画面を畳む。ここを通さずに /auth/logout へ移ると、上のコメントの // 3〜4 の隙間で古い画面が 401 を受け取る。 await page.goto('about:blank'); await page.goto('/auth/logout'); }