@moroo/wdio-slack-reporter
Version:
Reporter from WebdriverIO using Incoming webhook and Web API to send results to Slack.
1 lines • 13.6 kB
Source Map (JSON)
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["/**\n * Copyright (c) moroo\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { WebClient } from '@slack/web-api';\nimport { IncomingWebhook } from '@slack/webhook';\n\nimport { TimeoutError } from './types.js';\nimport { logger, waitForTimeout } from './utils.js';\n\nimport type {\n FilesUploadV2Options,\n FilesUploadV2Response,\n SlackIncomingWebhookOptions,\n SlackWebClientOptions,\n} from './types.js';\nimport type {\n ChatPostMessageArguments,\n ChatPostMessageResponse,\n FilesCompleteUploadExternalArguments,\n FilesCompleteUploadExternalResponse,\n FilesGetUploadURLExternalArguments,\n FilesGetUploadURLExternalResponse,\n FilesInfoArguments,\n FilesInfoResponse,\n FilesUploadV2Arguments,\n} from '@slack/web-api';\nimport type {\n IncomingWebhookResult,\n IncomingWebhookSendArguments,\n} from '@slack/webhook';\n\n/**\n * A client wrapper for Slack's WebClient API that simplifies common operations.\n *\n * This class provides methods for posting messages, uploading files, and interacting\n * with Slack's API in a more convenient way.\n *\n * @example\n * ```typescript\n * const slackWebClient = new SlackWebClient({\n * token: 'xoxb-your-token-here'\n * });\n *\n * // Post a message\n * await slackWebClient.postMessage({\n * channel: 'C12345',\n * text: 'Hello from WebdriverIO!'\n * });\n *\n * // Upload a file\n * await slackWebClient.upload({\n * channel_id: 'C12345',\n * file: '/path/to/report.html',\n * title: 'Test Report'\n * });\n * ```\n */\nclass SlackWebClient {\n private _token: string;\n private _client: WebClient;\n\n /**\n * Creates an instance of the Slack Web Client.\n *\n * @param {SlackWebClientOptions | undefined} options - The options for configuring the Slack client, excluding 'type' and 'channel'.\n */\n constructor(options: SlackWebClientOptions) {\n const { token, ...rest } = options;\n\n this._client = new WebClient(token, rest);\n this._token = token;\n }\n\n /**\n * Gets the authentication token for the Slack API.\n * @returns The current token value or undefined if not set.\n */\n public get token(): string | undefined {\n return this._token;\n }\n\n /**\n * Gets the Slack WebClient instance.\n * @returns {WebClient} The Slack WebClient instance used for API interactions.\n */\n public get client(): WebClient {\n return this._client;\n }\n\n /**\n * Posts a message to a Slack channel.\n *\n * @param payload - The arguments for posting a message to Slack\n * @returns A promise that resolves to the chat post message response\n * @throws Will throw and log an error if the message posting fails\n */\n public async postMessage(\n payload: ChatPostMessageArguments\n ): Promise<ChatPostMessageResponse> {\n try {\n const response = await this._client.chat.postMessage(payload);\n\n return response;\n } catch (error) {\n logger.error(error);\n throw error;\n }\n }\n\n /**\n * Uploads files to Slack using the files.uploadV2 API endpoint.\n *\n * @param payload - The file upload parameters conforming to FilesUploadV2Arguments\n * @param options - Optional configuration for the upload process\n * @param options.waitForUpload - Whether to wait for file processing completion (default: true)\n * @param options.timeout - Maximum time in milliseconds to wait for upload completion (default: 30000)\n * @param options.interval - Polling interval in milliseconds when checking upload status (default: 1000)\n *\n * @returns Promise resolving to the Slack API response (FilesUploadV2Response)\n *\n * @throws Will throw and log any errors encountered during the upload process\n *\n * @example\n * const result = await slackClient.uploadV2({\n * channel_id: \"C12345\",\n * file: someFileBuffer,\n * filename: \"report.pdf\",\n * token: \"xoxb-token\"\n * });\n */\n public async uploadV2(\n payload: FilesUploadV2Arguments,\n options?: FilesUploadV2Options\n ): Promise<FilesUploadV2Response> {\n const {\n waitForUpload = true,\n timeout = 30000,\n interval = 1000,\n } = options ?? {};\n // Slack 파일 업로드 API 호출\n try {\n const response = await this._client.filesUploadV2(payload);\n\n // 업로드가 성공적이면\n if (waitForUpload && response.ok) {\n const files = response.files?.flatMap((file) => file.files) ?? [];\n\n // 각 파일에 대해 업로드 완료까지 대기\n for await (const file of files) {\n try {\n if (file?.id) {\n await this.waitForUpload(\n file.id,\n payload.token,\n timeout,\n interval\n );\n }\n } catch (error) {\n logger.error(error);\n }\n }\n }\n\n // 최종 업로드 응답 반환\n return response;\n } catch (error) {\n logger.error(error);\n throw error; // 업로드 실패 시 에러 반환\n }\n }\n\n /**\n * Waits for a file to be processed and uploaded on Slack.\n * This method repeatedly checks the file info until the file's mimetype is available,\n * indicating that the file has been successfully processed.\n *\n * @param fileId - The ID of the file to check\n * @param timeout - Maximum time in milliseconds to wait for the file upload (default: 30000)\n * @param interval - Time in milliseconds between each check (default: 1000)\n * @returns A Promise that resolves to the FilesInfoResponse once the file is processed\n * @throws {TimeoutError} If the file is not processed within the specified timeout\n * @throws {Error} If any error occurs during the file info retrieval\n */\n public async waitForUpload(\n fileId: string,\n token?: string,\n timeout: number = 30000,\n interval: number = 1000\n ): Promise<FilesInfoResponse> {\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeout) {\n try {\n const response = await this.filesInfo({\n token: token ?? this._token,\n file: fileId,\n });\n\n if (response?.file?.mimetype) {\n return response;\n }\n } catch (error) {\n logger.error(error);\n throw error;\n }\n\n await waitForTimeout(interval);\n }\n\n throw new TimeoutError(\n `Timeout: No file info(mimetype) found within ${timeout / 1000} seconds`\n );\n }\n\n /**\n * Retrieves information about a file.\n *\n * @param options - Arguments for retrieving file information\n * @returns A promise that resolves to the file information response\n *\n * @example\n * ```typescript\n * const fileInfo = await client.filesInfo({\n * file: \"F123456789\"\n * });\n * ```\n */\n public async filesInfo(\n options: FilesInfoArguments\n ): Promise<FilesInfoResponse> {\n try {\n const response = await this._client.files.info(options);\n\n return response;\n } catch (error) {\n logger.error(error);\n throw error;\n }\n }\n\n /**\n * Retrieves an external upload URL for files.\n *\n * @param options - The arguments for the external upload URL request\n * @returns A promise that resolves to a FilesGetUploadURLExternalResponse\n * @throws Will throw and log any errors that occur during the request\n */\n public async getUploadURLExternal(\n options: FilesGetUploadURLExternalArguments\n ): Promise<FilesGetUploadURLExternalResponse> {\n try {\n const response = await this._client.files.getUploadURLExternal(options);\n\n return response;\n } catch (error) {\n logger.error(error);\n throw error;\n }\n }\n\n /**\n * Completes an external file upload process.\n * Calls the Slack API's files.completeUploadExternal method.\n *\n * @param options - Arguments required for completing an external upload\n * @returns A promise resolving to the response from the Slack API\n * @throws Will throw and log any errors that occur during the API call\n */\n public async completeUploadExternal(\n options: FilesCompleteUploadExternalArguments\n ): Promise<FilesCompleteUploadExternalResponse> {\n try {\n const response = await this._client.files.completeUploadExternal(options);\n\n return response;\n } catch (error) {\n logger.error(error);\n throw error;\n }\n }\n}\n\n/**\n * A class that provides an interface for sending messages to Slack via webhooks.\n *\n * This class wraps the Slack IncomingWebhook functionality and provides a simplified\n * interface for sending messages to a Slack channel.\n *\n * @example\n * ```typescript\n * const slackWebhookClient = new SlackWebhookClient({\n * webhook: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX',\n * username: 'WebdriverIO Reporter'\n * });\n *\n * await slackWebhookClient.send('Test message');\n * ```\n */\nclass SlackWebhookClient {\n private _url: string;\n private _webhook: IncomingWebhook;\n\n /**\n * Creates an instance of the Slack IncomingWebhook.\n * @param {SlackIncomingWebhookOptions} options - Configuration options for the Slack webhook.\n */\n constructor(options: SlackIncomingWebhookOptions) {\n const { webhook: url, ...rest } = options;\n\n this._url = url;\n this._webhook = new IncomingWebhook(url, rest);\n }\n\n /**\n * Gets the URL for the Slack webhook.\n * @returns The URL string for the Slack webhook.\n */\n public get url(): string {\n return this._url;\n }\n\n /**\n * Gets the Slack IncomingWebhook instance.\n *\n * @returns {IncomingWebhook} The configured Slack webhook client\n */\n public get webhook(): IncomingWebhook {\n return this._webhook;\n }\n\n /**\n * Sends a payload to Slack via webhook.\n *\n * @param payload - The content to send to Slack. Can be either a string or an IncomingWebhookSendArguments object.\n * @returns A Promise that resolves with the IncomingWebhookResult from Slack.\n * @throws Will re-throw any error that occurs during the send operation after logging it.\n */\n public async send(\n payload: string | IncomingWebhookSendArguments\n ): Promise<IncomingWebhookResult> {\n try {\n const response = await this._webhook.send(payload);\n\n return response;\n } catch (error) {\n logger.error(error);\n throw error;\n }\n }\n}\n\nexport { SlackWebClient, SlackWebhookClient };\n"],"mappings":"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","names":[]}