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
JavaScript
;
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;