web-dev-qa-db-ja.com

PuppeteerでHTTP応答をキャプチャする適切な方法は何ですか?

ユーザーのサインアップからhttp応答ステータスをキャプチャしようとしています。

私のコードは次のようになります:

_  it.only('returns a 400 response if email is taken', async () => {
    await page.goto(`${process.env.DOMAIN}/sign-up`)
    await page.waitFor('input[id="Full Name"]')

    await page.type('input[id="Full Name"]', 'Luke Skywalker')
    await page.type('input[id="Email"]', '[email protected]')
    await page.type('input[id="Password"]', 'LukeSkywalker123', {delay: 100})
    await page.click('input[type="submit"]', {delay: 1000})

    const response = await page.on('response', response => response)

    console.log('request status', response.status)
    // expect(response).toEqual(400)
  })
_

ドキュメントは、リクエストをインターセプトし、それを使用して実行する例を示しています。

_await page.setRequestInterception(true);
page.on('request', request => {
  request.respond({
    status: 404,
    contentType: 'text/plain',
    body: 'Not Found!'
  });
});
_

そして、私は他の多くのパターンと一緒に、無駄に似たパターンを試しました。私が行うすべてのことは、pageというステータスのない巨大なオブジェクトを返します。どんな助けでも大歓迎です。

機能したもの:

私を正しい方向に導いてくれた@tomahaugに感謝します。私の最初の問題は配置でした。リスナーは、リクエストが行われる前にセットアップされる必要があり、リクエストの直後にそれがありました。理にかなっています。私の最大の問題は、リスナーを変数に割り当てることでした。その結果、expectを最後の行として呼び出すことができました。これを変数に割り当てると、pageが返されました。必要なのは、リスナー内でテストを実行することだけでした。 done() throwsとerrorを使用している間、以下のようにテストを終了しました。私のコードの作業バージョン:

_it.only('returns a 400 response if email is taken', async () => {
    await page.goto(`${process.env.DOMAIN}/sign-up`)
    await page.waitFor('input[id="Full Name"]')

    await page.type('input[id="Full Name"]', 'Luke Skywalker')
    await page.type('input[id="Email"]', '[email protected]')
    await page.type('input[id="Password"]', 'LukeSkywalker123', {delay: 100})

    await page.on('response', response => {
      if (response.request().method === 'POST' && response.url === `${process.env.USERS_API_DOMAIN}/sessions`) {
        expect(response.status).toEqual(400)
      }
    })

    await page.click('input[type="submit"]', {delay: 1000})
  })

  after(async function () {
    await browser.close()
  })
_

これが他の誰かを助けることを願っています!

11
HolyMoly

私はあなたがそれらの線に沿って何かをすべきだと思います。コールバック関数doneに注意してください。

コードが行うことは、コードが応答のリスナーをアタッチし、送信ボタンをクリックすることです。応答を受信すると、ステータスコードをチェックしてアサートし、doneを呼び出してテストを終了します。

応答ハンドラが他の同時要求のイベントを発行する可能性があるため、コールバックでチェックしているのがフォームからの実際の応答であることをチェックするif- statementが必要になる場合があります。

it.only('returns a 400 response if email is taken', () => {
  await page.goto(`${process.env.DOMAIN}/sign-up`)
  await page.waitFor('input[id="Full Name"]')

  await page.type('input[id="Full Name"]', 'Luke Skywalker')
  await page.type('input[id="Email"]', '[email protected]')
  await page.type('input[id="Password"]', 'LukeSkywalker123', {delay: 100})

  await page.on('response', (response) => {
    if (
      response.request().method === 'POST' && 
      response.url === `${process.env.USERS_API_DOMAIN}/sessions`) 
    {
      expect(response.status).toEqual(400)
    }
  })

  await page.click('input[type="submit"]', {delay: 1000})
})

私はコードをテストしていませんが、それはあなたに正しい考えを与えるはずです。

編集:最終的にうまくいったことを反映するように調整されました。

6
tomahaug

_response.url_は関数であり、呼び出す必要があります。

_response.url()
_

response.request().methodの場合も同じです。

_response.request().method()
_
1
Dobrea Petrisor

リクエスト/レスポンスを操作する必要がある場合は、 page.setRequestInterception(true) およびpage.on/page.onceドキュメントに記載されているように )を使用します。

ただし、必要なのが応答について何かをアサートすることだけである場合、そうするための最も簡単で最も慣用的な方法は page.waitForResponse を使用することです。

const updateDashboardResponse = await page.waitForResponse(response =>
  response.url().includes('updateDashboard')
);
expect(updateDashboardResponse.status()).toBe(200);

これにより、テストフローを線形に保つことができ、page.onハンドラーがresponseイベントを受け取る前にテストを閉じることによる曖昧さを回避できます。

1
ericsoco