PlaywrightのSlackにカスタムメッセージでReportPortalのリンクを付けちゃおう

Slackにカスタムメッセージを送るのは簡単だけど、メッセージにReportPortalのLaunch(テスト実行とテスト結果を含むオブジェクト)のURLを追加するのがとても難しかった。結論を言うとカスタムメッセージは同期型のcustomLayoutと非同期型のcustomLayoutAsyncがあり、APIなどでデータを取ってきてカスタムメッセージに追加するには後者を利用する必要がある。

非同期のカスタムレイアウトに気がつけなかった理由

カスタムレイアウトの説明は以下にある。

Define your own Slack message custom layout

1つ目のサンプルをベースに作ってみたが、Slackへの通知で以下のようにエラーになった。

{
  "outcome": "error: {\n  \"code\": \"slack_webhook_http_error\",\n  \"original\": {\n    \"message\": \"Request failed with status code 400\",\n    \"name\": \"AxiosError\",\n    \"stack\": \"AxiosError: Request failed with status code 400\\n    at settle (/Users/daipresents/Work/playwright/node_modules/axios/lib/core/settle.js:19:12)\\n    at IncomingMessage.handleStreamEnd (/Users/daipresents/Work/playwright/node_modules/axios/lib/adapters/http.js:589:11)\\n    at IncomingMessage.emit (node:events:531:35)\\n    at endReadableNT (node:internal/streams/readable:1696:12)\\n    at processTicksAndRejections (node:internal/process/task_queues:82:21)\\n    at Axios.request (/Users/daipresents/Work/playwright/node_modules/axios/lib/core/Axios.js:45:41)\\n    at processTicksAndRejections (node:internal/process/task_queues:95:5)\\n    at IncomingWebhook.send (/Users/daipresents/Work/playwright/node_modules/@slack/webhook/src/IncomingWebhook.ts:70:24)\\n    at SlackWebhookClient.sendMessage (/Users/daipresents/Work/playwright/node_modules/playwright-slack-report/src/SlackWebhookClient.ts:36:16)\\n    at SlackReporter.onEnd (/Users/daipresents/Work/playwright/node_modules/playwright-slack-report/src/SlackReporter.ts:117:29)\\n    at ReporterV2Wrapper.onEnd (/Users/daipresents/Work/playwright/node_modules/playwright/lib/reporters/reporterV2.js:91:12)\\n    at wrapAsync (/Users/daipresents/Work/playwright/node_modules/playwright/lib/reporters/multiplexer.js:79:12)\\n    at Multiplexer.onEnd (/Users/daipresents/Work/playwright/node_modules/playwright/lib/reporters/multiplexer.js:51:25)\\n    at InternalReporter.onEnd (/Users/daipresents/Work/playwright/node_modules/playwright/lib/reporters/internalReporter.js:69:12)\\n    at Runner.runAllTests (/Users/daipresents/Work/playwright/node_modules/playwright/lib/runner/runner.js:77:28)\\n    at runTests (/Users/daipresents/Work/playwright/node_modules/playwright/lib/cli.js:132:93)\\n    at t.<anonymous> (/Users/daipresents/Work/playwright/node_modules/playwright/lib/cli.js:42:7)\",\n    \"config\": {\n      \"transitional\": {\n        \"silentJSONParsing\": true,\n        \"forcedJSONParsing\": true,\n        \"clarifyTimeoutError\": false\n      },\n      \"adapter\": [\n        \"xhr\",\n        \"http\"\n      ],\n      \"transformRequest\": [\n        null\n      ],\n      \"transformResponse\": [\n        null\n      ],\n      \"timeout\": 0,\n      \"xsrfCookieName\": \"XSRF-TOKEN\",\n      \"xsrfHeaderName\": \"X-XSRF-TOKEN\",\n      \"maxContentLength\": -1,\n      \"maxBodyLength\": -1,\n      \"env\": {},\n      \"headers\": {\n        \"Accept\": \"application/json, text/plain, */*\",\n        \"Content-Type\": \"application/json\",\n        \"User-Agent\": \"@slack:webhook/7.0.2 node/21.6.2 darwin/23.3.0\",\n        \"Content-Length\": \"21\",\n        \"Accept-Encoding\": \"gzip, compress, deflate, br\"\n      },\n      \"baseURL\": \"https://hooks.slack.com/services/XXXXXXXXXX\",\n      \"maxRedirects\": 0,\n      \"proxy\": false,\n      \"method\": \"post\",\n      \"url\": \"https://hooks.slack.com/services/XXXXXXXXXX\",\n      \"data\": \"{\\\"unfurl_links\\\":true}\"\n    },\n    \"code\": \"ERR_BAD_REQUEST\",\n    \"status\": 400\n  }\n}"
}

レイアウトからはSlackメッセージのブロックを返さなければならないのに非同期になりPromiseが返ってしまって400 Bad requestになっているみたい。

ここで1日詰まってしまったが、どうやってデフォルトのブロック作ってるのかソースを追っかけてみると、SlackWebhookClient.tscustomLayoutAsync たるものを発見。

Define your own Slack message custom layoutを改めてみてみると、別のサンプルのところにこんな記述があった。

In your, playwright.config.ts file, add these params (Make sure you use layoutAsync rather than layout):

これに気がつけなかったー。そのかわりに、Promise/async/awaitの勉強ができた。

Slackカスタムメッセージを作成する

PlaywrightからReportPortalにつなぎこみ、テストを実行すると最後に以下のログが出る。

ReportPortal Launch Link: http://localhost:8080/ui/#playwrightwithreportportalproject/launches/all/240

このリンクはclient-javascript というライブラリのreport-portal-clinet.js出力しているようだ。このリンクをクリックすれば、実行結果画面にすぐ行けるんだけど、このURLデータがどこにも見当たらないので自分で作るしかない。

幸いReportPortalにはAPIがたくさんあるので、今回は/launch/latestというREST APIを使える。リンクを作るためには↑だと 240のようなLaunchのIDが必要になる。

まずは非同期型のジェネレーターを作成する(サンプルコード)。

...

export async function generateReportPortalLayoutAsync (summaryResults: SummaryResults): Promise<Array<KnownBlock | Block>> {
  const blocks = await generateBlocks(summaryResults, summaryResults.failed);

  // add link to summary
  const permalink = await getReportLink();
  blocks[1]['text']['text'] = `${blocks[1]['text']['text']}\nSee: <${permalink}>`;
  return blocks;
}

...

デフォルトのカスタムメッセージはわかりやすいのでgenerateBlocks()を使って生成。そして、getReportLink()でReportPortalAPIからデータを取得しLaunchのリンクを作成する。これをgenerateBlocks() で作ったSlackのブロックに追記した。

そしてplaywright.config.tsには以下のように記述する。layoutAsync になっているので注意。

...
  reporter: [
    ['@reportportal/agent-js-playwright', reportPortalConfig],
    [
      "./node_modules/playwright-slack-report/dist/src/SlackReporter.js",
      {
        slackWebHookUrl: process.env.SLACK_HOOK,
        //channels: ["general"],
        sendResults: "always", // "always" , "on-failure", "off"
        layoutAsync: generateReportPortalLayoutAsync,
      },
    ],
  ],

...

結果は上のような感じになる。エラー箇所の簡易表示があり、詳細を見るならReportPortalを開けばいい。デバッグ捗りそう。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください