全体
[https://github.com/wand2016/e2etestautomation_puppeteer:embed:cite]
index.htmlのソース、仕様
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<noscript>
<meta http-equiv="refresh" content="0; URL=no-script.html" />
</noscript>
<title>
index.html
</title>
<script>
if (!navigator.cookieEnabled) {
location.replace('/no-cookie.html');
}
</script>
</head>
<body>
index.html
</body>
</html>
- JS無効時、
/no-script.html
にリダイレクト - Cookie無効時、
/no-cookie.html
に遷移
JavaScript無効時のテスト
test('JS無効だとno-script.htmlにリダイレクト', async () => {
await page.setJavaScriptEnabled(false);
await page.goto('http://localhost:8080/index.html', { timeout: 1000, waitUntil: 'domcontentloaded' });
// DOMContentLoaded後、metaタグによるリダイレクト待ち
await page.waitForNavigation({ timeout: 1000 });
await expect(page.title()).resolves.toMatch('no-script.html');
});
- これだけ:
page.setJavaScriptEnabled(false);
- Cookie無効判定にJavaScriptを使用するので、JavaScript無効のケースの考慮も必要
Cookie無効時のテスト
test('Cookie無効だとno-cookie.htmlにリダイレクト', async () => {
await page.evaluateOnNewDocument(() => {
Object.defineProperty(
navigator,
'cookieEnabled',
{ value: false }
);
});
await Promise.all([
page.goto('http://localhost:8080/index.html', { timeout: 1000, waitUntil: 'domcontentloaded' }),
// 同期スクリプト実行・遷移待ち
page.waitForNavigation({ timeout: 1000 })
]);
await expect(page.title()).resolves.toMatch('no-cookie.html');
});
index.html (抜粋)
if (!navigator.cookieEnabled) {
location.replace('/no-cookie.html');
}
navigator.cookieEnabled
を直接参照してCookie無効判定している、テスタビリティを全く考慮していないやばそうなコード(実在)- puppeteer自体にCookie無効をemulateする機能はない
- が、ドキュメント生成時にJSを実行することができ、そこでモック的な処理をさしはさむことができる
await page.evaluateOnNewDocument(() => {
Object.defineProperty(
navigator,
'cookieEnabled',
{ value: false }
);
});
-
navigator.cookieEnabledは「プロパティ」
- 通常のメンバ変数のように直接代入等をすることはできない
on chromium browser:
console.log(navigator.cookieEnabled); // true
navigator.cookieEnabled = false;
console.log(navigator.cookieEnabled); // still true
- が、configurableである:
Object.getOwnPropertyDescriptor(navigator.__proto__, 'cookieEnabled')
{set: undefined, enumerable: true, configurable: true, get: }
- ので、Object.definePropertyで上書き可能
Object.defineProperty(navigator, 'cookieEnabled', { value: false });
console.log(navigator.cookieEnabled); // false
- たまたまconfigurableだから助かったのであって、本当は
navigator.cookieEnabled
を直接参照すること自体良くないんですけど
awaitとPromiseの意識
-
雰囲気でawaitを書かない
- 裏のPromiseを意識する
- 並行して待たなければならないものはPromise.all()で包む
JavaScirpt無効判定
test('JS無効だとno-script.htmlにリダイレクト', async () => {
await page.setJavaScriptEnabled(false);
await page.goto('http://localhost:8080/index.html', { timeout: 1000, waitUntil: 'domcontentloaded' });
// DOMContentLoaded後、metaタグによるリダイレクト待ち
await page.waitForNavigation({ timeout: 1000 });
await expect(page.title()).resolves.toMatch('no-script.html');
});
- JavaScript無効時のリダイレクトの実装は
<meta>
タグによるHTTPリダイレクト
<noscript>
<meta http-equiv="refresh" content="0; URL=no-script.html" />
</noscript>
- これはDOMContentLoaded後に評価され実行されるので、まずpage.gotoをdomcontentloadedまで待ち終える:
await page.goto('http://localhost:8080/index.html', { timeout: 1000, waitUntil: 'domcontentloaded' });
- 続いてHTTPリダイレクトのナビゲーションを待つ:
await page.waitForNavigation({ timeout: 1000 });
Cookie無効判定
-
Cookie無効判定の実装としては、
<head>
タグの中でJavaScriptを同期的に実行している- すなわち、ページ遷移はDOMContentLoaded前に発生する
<script>
if (!navigator.cookieEnabled) {
location.replace('/no-cookie.html');
}
</script>
</head>
- ので、ページのDOMContentLoaded待ちと並行してページ遷移を待つ:
await Promise.all([
page.goto('http://localhost:8080/index.html', { timeout: 1000, waitUntil: 'domcontentloaded' }),
// 同期スクリプト実行・遷移待ち
page.waitForNavigation({ timeout: 1000 })
]);