UNPKG

omni-dashboard-playwright-reporter

Version:

Playwright client for publishing test results to Omni Dashboard - Transform Your Test Automation with AI-Powered Insights

237 lines (236 loc) 10.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.OmniPlaywrightClient = void 0; const test_1 = require("@playwright/test"); const chalk_1 = __importDefault(require("chalk")); const fs = __importStar(require("fs")); const path = __importStar(require("path")); class OmniPlaywrightClient { constructor(config) { this.config = config; } async getContext() { if (!this.context) { this.context = await test_1.request.newContext({ baseURL: this.config.baseUrl, extraHTTPHeaders: { 'x-api-key': this.config.apiKey, 'Content-Type': 'application/json' } }); } return this.context; } async createBuild(requestBody) { const url = `${this.config.baseUrl}/projects/${this.config.projectId}/builds`; console.log("Create Build URL:", url); console.log("Create Build Request Payload: ", JSON.stringify(requestBody, null, 2)); try { const context = await this.getContext(); const response = await context.post(url, { data: requestBody }); const body = await response.json(); console.log("Create Build Response (%s) %s:", response.status(), JSON.stringify(body, null, 2)); return body; } catch (error) { console.error("Error creating build:", error.message); throw error; } } async completeBuild(requestBody) { const url = `${this.config.baseUrl}/projects/${this.config.projectId}/builds?build_id=${requestBody.build_id}`; console.log("Complete Build URL:", url); console.log("Complete Build Request Payload: ", JSON.stringify(requestBody, null, 2)); try { const context = await this.getContext(); const response = await context.patch(url, { data: requestBody }); const body = await response.json(); console.log("Complete Build Response (%s) %s:", response.status(), JSON.stringify(body, null, 2)); return body; } catch (error) { console.error("Error completing build:", error.message); throw error; } } async uploadTestCase(test, result, buildId) { const url = `${this.config.baseUrl}/projects/${this.config.projectId}/test-cases`; console.log("Upload TestCase URL:", url); const payload = this.createTestCasePayload(test, result, buildId); console.log("Upload TestCase Request Payload: ", JSON.stringify(payload, null, 2)); try { const context = await this.getContext(); const response = await context.post(url, { data: payload }); const body = await response.json(); console.log("Upload TestCase Response (%s) %s:", response.status(), JSON.stringify(body, null, 2)); const uploadTestCaseResponse = body; return uploadTestCaseResponse; } catch (error) { console.error("In Upload TestCase. Error uploading test case:", error.message); throw error; } } createTestCasePayload(test, result, buildId) { const title = test.title; const test_status = result.status; // Create steps from test steps const steps = result.steps.map((step, index) => ({ name: step.title, sequence_number: index + 1, duration: step.duration, status: step.error ? 'failed' : 'passed', error_message: step.error?.message, stack_trace: step.error?.stack })); // Create stdout entries const stdout = [{ timestamp: new Date().toISOString(), level: test_status === 'passed' ? 'INFO' : 'ERROR', message: `${title} ${test_status}` }]; // Create screenshots entries const screenshots = result.attachments .filter((att) => att.contentType === 'image/png' && att.path) .map((att) => ({ name: att.path, timestamp: new Date().toISOString() })); // Create traces entries const traces = result.attachments .filter((att) => att.name === 'trace' && att.contentType === 'application/zip') .map((att) => ({ name: att.path })); // Create annotations from test annotations const annotations = result.annotations.map((ann) => ({ type: ann.type, description: ann.description })); const singleTestCase = { name: title, module: annotations.find((ann) => ann.type === 'module')?.description || 'Others', priority: annotations.find((ann) => ann.type === 'priority')?.description, tags: test.tags?.map((tag) => tag.replace(/^@/, '')) || [], status: test_status, duration: result.duration, steps, stdout, screenshots, traces, annotations, error_message: result.error?.message, error_stack_trace: result.error?.stack }; return { build_id: buildId, test_cases: [singleTestCase] }; } async uploadScreenshots(test_case) { if (test_case.screenshots_s3_paths?.length > 0) { console.log("Screenshots to be uploaded:", test_case.screenshots_s3_paths.length); await Promise.all(test_case.screenshots_s3_paths.map(async (screenshot) => { console.log("Uploading Screenshot:", screenshot.local_path); try { const filePath = path.resolve(screenshot.local_path); const fileData = await fs.promises.readFile(filePath); console.log("Upload URL:", screenshot.upload_url); const response = await fetch(screenshot.upload_url, { method: 'PUT', headers: { 'Content-Type': 'image/png', 'Content-Length': fileData.length.toString() }, body: fileData }); console.log(chalk_1.default.green('Uploaded screenshot:', screenshot.name, 'Status:', response.status)); if (!response.ok) { const errorText = await response.text(); console.error(chalk_1.default.red('S3 upload failed:', errorText)); throw new Error(`S3 upload failed with status ${response.status}: ${errorText}`); } } catch (uploadErr) { console.error(chalk_1.default.red('Failed to upload screenshot:', screenshot.name), uploadErr); throw uploadErr; } })); } } async uploadTraces(test_case) { if (test_case.traces_s3_paths?.length > 0) { console.log("Traces to be uploaded:", test_case.traces_s3_paths.length); await Promise.all(test_case.traces_s3_paths.map(async (trace) => { console.log("Uploading Trace:", trace.name); console.log("Uploading Trace Path:", trace.local_path); try { const filePath = path.resolve(trace.local_path); const fileData = await fs.promises.readFile(filePath); console.log("Upload URL:", trace.upload_url); const response = await fetch(trace.upload_url, { method: 'PUT', headers: { 'Content-Type': 'application/zip', 'Content-Length': fileData.length.toString() }, body: fileData }); console.log(chalk_1.default.green('Uploaded trace:', trace.name, 'Status:', response.status)); if (!response.ok) { const errorText = await response.text(); console.error(chalk_1.default.red('S3 upload failed:', errorText)); throw new Error(`S3 upload failed with status ${response.status}: ${errorText}`); } } catch (uploadErr) { console.error(chalk_1.default.red('Failed to upload trace:', trace.name), uploadErr); throw uploadErr; } })); } } } exports.OmniPlaywrightClient = OmniPlaywrightClient;