UNPKG

@chtsinc/ch-playwright-report

Version:

Custom Playwright Reporter that logs test and execution results to MongoDB

252 lines 12 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const ch_logger_1 = require("@chtsinc/ch-logger"); const ch_javascript_sdk_1 = require("@chtsinc/ch-javascript-sdk"); const execution_context_loader_1 = require("./reporter-setup/execution-context-loader"); const service_config_loader_1 = require("./reporter-setup/service-config-loader"); const test_report_util_1 = require("./utils/test-report-util"); const execution_report_util_1 = require("./utils/execution-report-util"); const session_report_util_1 = require("./utils/session-report-util"); const test_status_summary_util_1 = require("./utils/test-status-summary-util"); const video_upload_util_1 = require("./utils/video-upload-util"); const validation_util_1 = require("./utils/validation-util"); const email_util_1 = require("./utils/email-util"); const report_upload_util_1 = require("./utils/report-upload-util"); class CHPlaywrightReporter { constructor() { this.logger = (0, ch_logger_1.getLogger)(); this.isInitSuccess = false; this.executionReport = null; this.testStatusSummary = null; this.videosCollection = []; } async onBegin(_config, suite) { //initializing reporter await this.initializeReport(); if (!this.isInitSuccess) { return; } try { //setting browser name this.setBrowserNameForReport(_config, suite); //creating execution report this.executionReport = execution_report_util_1.ExecutionReportUtil.createExecutionReport(this.executionContext); this.executionReport.expectedTestCounts = suite.allTests().length; //exporting execution report await this.exportService.exportExecutionReport(this.executionReport); this.testStatusSummary = new test_status_summary_util_1.TestStatusSummaryUtil(); this.logger.info(`CHPlaywrightReporter started for executionId=${this.executionReport.executionId} with totalTests=${this.executionReport.expectedTestCounts} and start time = ${this.executionReport.executionStartTime}`); } catch (error) { this.isInitSuccess = false; this.logger.error("CHPlaywrightReporter: Error during onBegin", error); } } async onTestBegin(_test, _result) { } async onTestEnd(test, result) { if (!this.isInitSuccess) { return; } //creating test report let testReport = test_report_util_1.TestReportUtil.createTestReport(this.executionContext); try { //processing test report testReport = test_report_util_1.TestReportUtil.populateTestReport(test, result, testReport); //exporting test report await this.exportService.exportTestReport(testReport); this.logger.info(`CHPlaywrightReporter – Test completed | test=${test.title} | status=${result.status} | duration=${result.duration}ms`); this.testStatusSummary?.addResult(result); } catch (error) { this.logger.error("CHPlaywrightReporter: Error uploading test report", error); } try { this.collectVideoPath(test, result, testReport.sessionId); } catch (error) { this.logger.error("CHPlaywrightReporter: Error collecting test videos", error); } } async onStepBegin(_test, _result, _step) { } async onStepEnd(_test, _result, _step) { } async onEnd(result) { if (!this.isInitSuccess) { return; } try { this.executionReport = validation_util_1.ValidationUtil.assertNotNull(this.executionReport, "ExecutionReport"); //processing execution report this.executionReport = execution_report_util_1.ExecutionReportUtil.finalizeExecutionReport(this.executionReport); //exporting execution report await this.exportService.exportExecutionReport(this.executionReport); this.logger.info(`CHPlaywrightReporter completed for executionId=${this.executionReport.executionId} - duration=${result.duration}ms`); } catch (error) { this.logger.error("CHPlaywrightReporter: Error uploading execution report", error); } //uploading and exporting test videos to session reports try { const isVideosUploaded = await this.processVideoCollection(); if (isVideosUploaded) { this.logger.info(`CHPlaywrightReporter - Completed video upload`); } else { this.logger.info(`CHPlaywrightReporter - No videos to upload`); } } catch (error) { this.logger.error("CHPlaywrightReporter: Error uploading videos", error); } //uploading report let reportUrl = null; if (this.servicesConfig?.isReportUploadEnabled == true) { try { reportUrl = await report_upload_util_1.ReportUploadUtil.uploadReportFile(this.servicesConfig, this.testStatusSummary, this.executionReport); if (!reportUrl) { this.logger.info(`CHPlaywrightReporter: Report URL is null`); } else { this.logger.info(`CHPlaywrightReporter - Completed Report upload`); } } catch (error) { this.logger.error("CHPlaywrightReporter: Error uploading report", error); } } else { this.logger.debug(`CHPlaywrightReporter: Report upload is not enabled`); } //sending test summary email const files = ""; if (this.servicesConfig?.isEmailEnabled == true) { try { await email_util_1.EmailUtil.sendEmail(this.servicesConfig, this.testStatusSummary, this.executionReport, reportUrl, files); this.logger.info(`CHPlaywrightReporter - Test summary email sent`); } catch (error) { this.logger.error("CHPlaywrightReporter: Error sending email", error); } } else { this.logger.debug(`CHPlaywrightReporter: Email Service is not enabled`); } try { this.exportService.stopService(); } catch (error) { this.logger.error("CHPlaywrightReporter: Error in shutting down services", error); } } collectVideoPath(test, result, id) { if (this.servicesConfig?.isVideoUploadEnabled == true) { try { const videoPath = this.getVideoPath(result); this.videosCollection.push({ videoPath: videoPath, sessionId: id, }); } catch (error) { this.logger.debug(`CHPlaywrightReporter: No video found for test: ${test.title} - ${error}`); } } else { this.logger.debug(`CHPlaywrightReporter: Video upload is not enabled for ${test.title}`); } } async processVideoCollection() { if (this.videosCollection.length == 0) { this.logger.info(`CHPlaywrightReporter: Videos collection empty`); return false; } //processing videos from collection, uploading for (const { videoPath, sessionId } of this.videosCollection) { let sessionReport = session_report_util_1.SessionReportUtil.createSessionReport(this.executionContext, sessionId); let videoUrl = null; videoUrl = await video_upload_util_1.VideoUploadUtil.uploadVideoFile(videoPath, this.servicesConfig, sessionReport); if (!videoUrl) { this.logger.error(`CHPlaywrightReporter:Video upload failed (session=${sessionReport.sessionInfo.sessionId}, exec=${sessionReport.executionId}) for file: ${videoPath}`); continue; } //processing session report sessionReport = session_report_util_1.SessionReportUtil.populateSessionReport(videoUrl, sessionReport); try { //exporting session report await this.exportService.exportSessionReport(sessionReport); } catch (error) { this.logger.error(`CHPlaywrightReporter: Failed to export session report for video: ${videoUrl}`, error); } } return true; } getVideoPath(result) { if (!result.attachments) { throw new Error("No attachments found in the test result."); } const videoAttachments = result.attachments .filter((att) => att.name === "video" && typeof att.path === "string" && fs_1.default.existsSync(att.path)) .map((att) => ({ path: att.path, size: fs_1.default.statSync(att.path).size, })); if (videoAttachments.length === 0) { throw new Error("No valid video attachment found or video file does not exist."); } const largestVideo = videoAttachments.reduce((max, current) => current.size > max.size ? current : max); return largestVideo.path; } async initializeReport() { this.logger.info(`CHPlaywrightReporter: Initializing Reporter`); try { this.executionContext = validation_util_1.ValidationUtil.assertNotNull((0, execution_context_loader_1.loadExecutionContext)(), "ExecutionContext"); this.servicesConfig = validation_util_1.ValidationUtil.assertNotNull((0, service_config_loader_1.loadServiceConfig)(), "ServicesContext"); const serviceConfigPath = path_1.default.resolve(process.cwd(), "ch-services.json"); this.exportService = validation_util_1.ValidationUtil.assertNotNull(new ch_javascript_sdk_1.ExportService(serviceConfigPath), "ExportService"); await this.exportService.startService(); this.isInitSuccess = true; } catch (error) { this.logger.error("CHPlaywrightReporter: Error initializing reporter", error); } } getBrowserNameByProjectConfig(config, suite) { const runningProjectName = suite.suites.length > 0 ? suite.suites[0]?.title : ""; const matchedProject = config.projects.find((project) => project.name === runningProjectName); const playwrightBrowser = matchedProject?.use?.browserName || matchedProject?.use?.defaultBrowserType || "chromium"; switch (playwrightBrowser.toLowerCase()) { case "chromium": return "Chrome"; case "webkit": return "Safari"; case "firefox": return "Firefox"; default: return "Chrome"; } } setBrowserNameForReport(config, suite) { const playwrightBrowserName = this.getBrowserNameByProjectConfig(config, suite); const formFactor = this.executionContext.formFactor?.toLowerCase(); const isMobileOrTablet = formFactor === "mobile" || formFactor === "tablet"; const executionContextBrowser = this.executionContext.browserName; const isBrowserNameMissing = !executionContextBrowser || executionContextBrowser.trim() === ""; if (isBrowserNameMissing) { this.executionContext.browserName = playwrightBrowserName; } if (isMobileOrTablet && playwrightBrowserName.toLowerCase() === "safari") { this.executionContext.browserName = playwrightBrowserName; } } } exports.default = CHPlaywrightReporter; //# sourceMappingURL=ch-playwright-reporter.js.map