TestCafeでロールでログインした後の画面が表示されない問題
現象
TestCafe (1.14.0)でRole機能を使用して開発しているシステムにログインしたあとの画面が正しいか検証しようとしたところ、空白の画面が表示されるのみでテストが失敗するという現象が起こった。
フォーム認証のアプリケーション
role.ts
import { Role, Selector } from "testcafe";
const regularUser = Role('http://example.com/login', async t => {
await t
.typeText(Selector('#account-code'), 'sampleuser')
.typeText(Selector('#password'), 'hogehoge')
.click(Selector('#login-button'));
});
一般ユーザー(sampleuser)のロールを作成し、ログインページ(http://example.com/login)を呼び出し、アカウントとパスワードを入力してログインボタンを押すとログインをするとホーム画面に遷移をするという平凡なアプリケーション。
home.ts
import { Selector } from "testcafe";
import { regularUser } from "./roles";
fixture 'ホーム画面のテスト';
test('初期画面の検証', async t => {
await t
.useRole(regularUser)
.expect(Selector('h1').innerText, 'ホーム');
});
home.tsを実行するとロールに記述したように一般ユーザーとしてアカウントとパスワードを入力してログインボタンが押されホーム画面が一瞬(0.2秒)表示されたかと思うとブラウザが真っ白になった。
1) Cannot obtain information about the node because the specified selector does not match any node in the DOM tree.
> | Selector('h1')
5 |test('初期画面の検証', async t => {
6 | await t
7 | .useRole(regularUser)
> 8 | .expect(Selector('h1'.innerText).eql('ホーム')
9 |});
10 |
11 |
1/1 failed (26s)
5秒ほどすると上記のようなエラーをコンソールに入ってテストが失敗した。
解決
しばらく悩んだがAuthenticationのTrouble ShoothingのTest Actions Fail After Authenticationに答えが書かれていました。
In order to guarantee seamless test execution, browsers that run TestCafe tests should always fetch the tested page from the TestCafe proxy server. This ensures that automation scripts on the page are in sync with the server side.
However, if the browser uses a cached copy of the page, automation mechanisms may be interrupted. Among other issues, this could reset authentication data in the cookies, local and session storage during navigation.
If tests fail unexpectedly after authentication, try the following:
Enable the preserveUrl option to disable automatic navigation.
If preserveUrl does not fix the issue, disable page caching. Note that this slows down test execution.
ということで、options.preserveUIを追加したところ、問題なく実行できた。
import { Role, Selector } from "testcafe";
const regularUser = Role('http://example.com/login', async t => {
await t
.typeText(Selector('#account-code'), 'sampleuser')
.typeText(Selector('#password'), 'hogehoge')
.click(Selector('#login-button'));
}, {preserveUI: true});
Discussion