🚀. Socket Launch Week Day 2:Introducing Manifest Alerts.Learn more
Sign In

@allurereport/plugin-api

Package Overview
Dependencies
Maintainers
2
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@allurereport/plugin-api - npm Package Compare versions

Comparing version
3.0.0-beta.17
to
3.0.0-beta.18
+85
dist/charts.d.ts
import type { BaseTrendSliceMetadata, ChartId, ChartType, HistoryDataPoint, PieSlice, SeverityLevel, Statistic, TestResult, TestStatus, TrendPoint, TrendPointId, TrendSlice, TrendSliceId } from "@allurereport/core-api";
import { ChartDataType, ChartMode } from "@allurereport/core-api";
import type { PluginContext } from "./plugin.js";
export type ExecutionIdFn = (executionOrder: number) => string;
export type ExecutionNameFn = (executionOrder: number) => string;
export type TrendMetadataFnOverrides = {
executionIdAccessor?: ExecutionIdFn;
executionNameAccessor?: ExecutionNameFn;
};
export type TrendDataType = TestStatus | SeverityLevel;
export type TrendCalculationResult<T extends TrendDataType> = {
points: Record<TrendPointId, TrendPoint>;
series: Record<T, TrendPointId[]>;
};
export interface GenericTrendChartData<SeriesType extends string, Metadata extends BaseTrendSliceMetadata = BaseTrendSliceMetadata> {
type: ChartType.Trend;
dataType: ChartDataType;
mode: ChartMode;
title?: string;
points: Record<TrendPointId, TrendPoint>;
slices: Record<TrendSliceId, TrendSlice<Metadata>>;
series: Record<SeriesType, TrendPointId[]>;
min: number;
max: number;
}
export type StatusTrendChartData = GenericTrendChartData<TestStatus>;
export type SeverityTrendChartData = GenericTrendChartData<SeverityLevel>;
export type TrendChartData = StatusTrendChartData | SeverityTrendChartData;
export type GeneratedChartData = TrendChartData | PieChartData | ComingSoonChartData;
export type GeneratedChartsData = Record<ChartId, GeneratedChartData>;
export type TrendStats<T extends TrendDataType> = Record<T, number>;
export type TrendChartOptions = {
type: ChartType.Trend;
dataType: ChartDataType;
mode?: ChartMode;
title?: string;
limit?: number;
metadata?: TrendMetadataFnOverrides;
};
export type PieChartOptions = {
type: ChartType.Pie;
title?: string;
};
export type ComingSoonChartOptions = {
type: ChartType.HeatMap | ChartType.Bar | ChartType.Funnel | ChartType.TreeMap;
title?: string;
};
export type ChartOptions = TrendChartOptions | PieChartOptions | ComingSoonChartOptions;
export interface PieChartData {
type: ChartType.Pie;
title?: string;
slices: PieSlice[];
percentage: number;
}
export interface ComingSoonChartData {
type: ChartType.HeatMap | ChartType.Bar | ChartType.Funnel | ChartType.TreeMap;
title?: string;
}
export declare const createEmptySeries: <T extends TrendDataType>(items: readonly T[]) => Record<T, string[]>;
export declare const calculatePercentValues: <T extends TrendDataType>(stats: Record<T, number>, executionId: string, itemType: readonly T[]) => TrendCalculationResult<T>;
export declare const getTrendDataGeneric: <T extends TrendDataType, M extends BaseTrendSliceMetadata>(stats: Record<T, number>, reportName: string, executionOrder: number, itemType: readonly T[], chartOptions: TrendChartOptions) => GenericTrendChartData<T, M>;
export declare const createEmptyStats: <T extends TrendDataType>(items: readonly T[]) => TrendStats<T>;
export declare const normalizeStatistic: <T extends TrendDataType>(statistic: Partial<TrendStats<T>>, itemType: readonly T[]) => TrendStats<T>;
export declare const mergeTrendDataGeneric: <T extends TrendDataType, M extends BaseTrendSliceMetadata>(trendData: GenericTrendChartData<T, M>, trendDataPart: GenericTrendChartData<T, M>, itemType: readonly T[]) => GenericTrendChartData<T, M>;
export declare const DEFAULT_CHART_HISTORY_LIMIT = 10;
export declare const getPieChartData: (stats: Statistic, chartOptions: PieChartOptions) => PieChartData;
export declare const generatePieChart: (options: PieChartOptions, stores: {
statistic: Statistic;
}) => PieChartData;
export declare const generateComingSoonChart: (options: ComingSoonChartOptions) => ComingSoonChartData;
export interface TrendDataAccessor<T extends TrendDataType> {
getCurrentData: (trs: TestResult[], stats: Statistic) => TrendStats<T>;
getHistoricalData: (historyPoint: HistoryDataPoint) => TrendStats<T>;
getAllValues: () => readonly T[];
}
export declare const generateTrendChartGeneric: <T extends TrendDataType>(options: TrendChartOptions, stores: {
trs: TestResult[];
statistic: Statistic;
history: HistoryDataPoint[];
}, context: PluginContext, dataAccessor: TrendDataAccessor<T>) => GenericTrendChartData<T> | undefined;
export declare const generateTrendChart: (options: TrendChartOptions, stores: {
trs: TestResult[];
statistic: Statistic;
history: HistoryDataPoint[];
}, context: PluginContext) => TrendChartData | undefined;
import { ChartDataType, ChartMode, getPieChartValues } from "@allurereport/core-api";
import { severityTrendDataAccessor } from "./severityTrendAccessor.js";
import { statusTrendDataAccessor } from "./statusTrendAccessor.js";
export const createEmptySeries = (items) => items.reduce((acc, item) => ({ ...acc, [item]: [] }), {});
export const calculatePercentValues = (stats, executionId, itemType) => {
const points = {};
const series = createEmptySeries(itemType);
const values = Object.values(stats);
const total = values.reduce((sum, value) => sum + value, 0);
if (total === 0) {
return { points, series };
}
itemType.forEach((item) => {
const pointId = `${executionId}-${item}`;
const value = stats[item] ?? 0;
points[pointId] = {
x: executionId,
y: value / total,
};
series[item].push(pointId);
});
return { points, series };
};
const calculateRawValues = (stats, executionId, itemType) => {
const points = {};
const series = createEmptySeries(itemType);
itemType.forEach((item) => {
const pointId = `${executionId}-${item}`;
const value = stats[item] ?? 0;
points[pointId] = {
x: executionId,
y: value,
};
series[item].push(pointId);
});
return { points, series };
};
export const getTrendDataGeneric = (stats, reportName, executionOrder, itemType, chartOptions) => {
const { type, dataType, title, mode = ChartMode.Raw, metadata = {} } = chartOptions;
const { executionIdAccessor, executionNameAccessor } = metadata;
const executionId = executionIdAccessor ? executionIdAccessor(executionOrder) : `execution-${executionOrder}`;
const { points, series } = mode === ChartMode.Percent
? calculatePercentValues(stats, executionId, itemType)
: calculateRawValues(stats, executionId, itemType);
const slices = {};
const pointsAsArray = Object.values(points);
const pointsCount = pointsAsArray.length;
const values = pointsAsArray.map((point) => point.y);
const min = pointsCount ? Math.min(...values) : 0;
const max = pointsCount ? Math.max(...values) : 0;
if (pointsCount > 0) {
const executionName = executionNameAccessor ? executionNameAccessor(executionOrder) : reportName;
slices[executionId] = {
min,
max,
metadata: {
executionId,
executionName,
},
};
}
return {
type,
dataType,
mode,
title,
points,
slices,
series,
min,
max,
};
};
export const createEmptyStats = (items) => items.reduce((acc, item) => ({ ...acc, [item]: 0 }), {});
export const normalizeStatistic = (statistic, itemType) => {
return itemType.reduce((acc, item) => {
acc[item] = statistic[item] ?? 0;
return acc;
}, {});
};
export const mergeTrendDataGeneric = (trendData, trendDataPart, itemType) => {
return {
...trendData,
points: {
...trendData.points,
...trendDataPart.points,
},
slices: {
...trendData.slices,
...trendDataPart.slices,
},
series: Object.entries(trendDataPart.series).reduce((series, [group, pointIds]) => {
if (Array.isArray(pointIds)) {
return {
...series,
[group]: [...(trendData.series?.[group] || []), ...pointIds],
};
}
return series;
}, trendData.series || createEmptySeries(itemType)),
min: Math.min(trendData.min ?? Infinity, trendDataPart.min),
max: Math.max(trendData.max ?? -Infinity, trendDataPart.max),
};
};
export const DEFAULT_CHART_HISTORY_LIMIT = 10;
export const getPieChartData = (stats, chartOptions) => ({
type: chartOptions.type,
title: chartOptions?.title,
...getPieChartValues(stats),
});
export const generatePieChart = (options, stores) => {
const { statistic } = stores;
return getPieChartData(statistic, options);
};
export const generateComingSoonChart = (options) => {
return {
type: options.type,
title: options.title,
};
};
export const generateTrendChartGeneric = (options, stores, context, dataAccessor) => {
const { trs = [], statistic, history } = stores;
const { limit } = options;
const historyLimit = limit && limit > 0 ? Math.max(0, limit - 1) : undefined;
const currentData = dataAccessor.getCurrentData(trs, statistic);
const limitedHistoryPoints = historyLimit !== undefined ? history.slice(-historyLimit) : history;
const firstOriginalIndex = historyLimit !== undefined ? Math.max(0, history.length - historyLimit) : 0;
const convertedHistoryPoints = limitedHistoryPoints.map((point, index) => {
const originalIndex = firstOriginalIndex + index;
return {
name: point.name,
originalIndex,
statistic: dataAccessor.getHistoricalData(point),
};
});
const allValues = dataAccessor.getAllValues();
const currentTrendData = getTrendDataGeneric(normalizeStatistic(currentData, allValues), context.reportName, history.length + 1, allValues, options);
const historicalTrendData = convertedHistoryPoints.reduce((acc, historyPoint) => {
const trendDataPart = getTrendDataGeneric(normalizeStatistic(historyPoint.statistic, allValues), historyPoint.name, historyPoint.originalIndex + 1, allValues, options);
return mergeTrendDataGeneric(acc, trendDataPart, allValues);
}, {
type: options.type,
dataType: options.dataType,
mode: options.mode,
title: options.title,
points: {},
slices: {},
series: createEmptySeries(allValues),
min: Infinity,
max: -Infinity,
});
return mergeTrendDataGeneric(historicalTrendData, currentTrendData, allValues);
};
export const generateTrendChart = (options, stores, context) => {
const newOptions = { limit: DEFAULT_CHART_HISTORY_LIMIT, ...options };
const { dataType } = newOptions;
if (dataType === ChartDataType.Status) {
return generateTrendChartGeneric(newOptions, stores, context, statusTrendDataAccessor);
}
else if (dataType === ChartDataType.Severity) {
return generateTrendChartGeneric(newOptions, stores, context, severityTrendDataAccessor);
}
};
import type { SeverityLevel } from "@allurereport/core-api";
import type { TrendDataAccessor } from "./charts.js";
export declare const severityTrendDataAccessor: TrendDataAccessor<SeverityLevel>;
import { severityLabelName, severityLevels } from "@allurereport/core-api";
import { createEmptyStats } from "./charts.js";
const processTestResults = (testResults) => {
return testResults.reduce((acc, test) => {
const severityLabel = test.labels?.find((label) => label.name === severityLabelName);
const severity = severityLabel?.value?.toLowerCase();
if (severity) {
acc[severity] = (acc[severity] ?? 0) + 1;
}
return acc;
}, createEmptyStats(severityLevels));
};
export const severityTrendDataAccessor = {
getCurrentData: (trs) => {
return processTestResults(trs);
},
getHistoricalData: (historyPoint) => {
return processTestResults(Object.values(historyPoint.testResults));
},
getAllValues: () => severityLevels,
};
import type { TestStatus } from "@allurereport/core-api";
import type { TrendDataAccessor } from "./charts.js";
export declare const statusTrendDataAccessor: TrendDataAccessor<TestStatus>;
import { statusesList } from "@allurereport/core-api";
import { createEmptyStats } from "./charts.js";
export const statusTrendDataAccessor = {
getCurrentData: (trs, stats) => {
return {
...createEmptyStats(statusesList),
...stats,
};
},
getHistoricalData: (historyPoint) => {
return Object.values(historyPoint.testResults).reduce((stat, test) => {
if (test.status) {
stat[test.status] = (stat[test.status] ?? 0) + 1;
}
return stat;
}, createEmptyStats(statusesList));
},
getAllValues: () => statusesList,
};
+1
-1

@@ -13,4 +13,4 @@ import type { DefaultLabelsConfig, EnvironmentsConfig, ReportVariables } from "@allurereport/core-api";

plugins?: Record<string, PluginDescriptor>;
appendHistory?: boolean;
qualityGate?: QualityGateConfig;
appendHistory?: boolean;
allureService?: {

@@ -17,0 +17,0 @@ url?: string;

export * from "./config.js";
export type * from "./plugin.js";
export type * from "./qualityGate.js";
export type * from "./store.js";
export type * from "./resultFile.js";
export type * from "./qualityGate.js";
export * from "./utils/misc.js";
export * from "./utils/tree.js";
export * from "./utils/summary.js";
export * from "./charts.js";
export * from "./severityTrendAccessor.js";
export * from "./statusTrendAccessor.js";

@@ -5,1 +5,4 @@ export * from "./config.js";

export * from "./utils/summary.js";
export * from "./charts.js";
export * from "./severityTrendAccessor.js";
export * from "./statusTrendAccessor.js";

@@ -1,2 +0,4 @@

import type { CiDescriptor, Statistic, TestResult, TestStatus } from "@allurereport/core-api";
import type { AttachmentLink, CiDescriptor, Statistic, TestError, TestResult, TestStatus } from "@allurereport/core-api";
import type { QualityGateValidationResult } from "./qualityGate.js";
import type { ResultFile } from "./resultFile.js";
import type { AllureStore } from "./store.js";

@@ -42,12 +44,34 @@ export interface PluginDescriptor {

}
export interface ExitCode {
actual?: number;
original: number;
}
export interface PluginGlobals {
exitCode: ExitCode;
errors: TestError[];
attachments: AttachmentLink[];
}
export interface BatchOptions {
maxTimeout?: number;
}
export interface Realtime {
onTestResults(listener: (trIds: string[]) => Promise<void>, options?: BatchOptions): void;
onTestFixtureResults(listener: (tfrIds: string[]) => Promise<void>, options?: BatchOptions): void;
onAttachmentFiles(listener: (afIds: string[]) => Promise<void>, options?: BatchOptions): void;
export interface RealtimeSubscriber {
onGlobalAttachment(listener: (attachment: ResultFile) => Promise<void>): () => void;
onGlobalExitCode(listener: (payload: ExitCode) => Promise<void>): () => void;
onGlobalError(listener: (error: TestError) => Promise<void>): () => void;
onQualityGateResults(listener: (payload: QualityGateValidationResult[]) => Promise<void>): () => void;
onTestResults(listener: (trIds: string[]) => Promise<void>, options?: BatchOptions): () => void;
onTestFixtureResults(listener: (tfrIds: string[]) => Promise<void>, options?: BatchOptions): () => void;
onAttachmentFiles(listener: (afIds: string[]) => Promise<void>, options?: BatchOptions): () => void;
}
export interface RealtimeEventsDispatcher {
sendGlobalAttachment(attachment: ResultFile): void;
sendGlobalExitCode(payload: ExitCode): void;
sendGlobalError(error: TestError): void;
sendQualityGateResults(payload: QualityGateValidationResult[]): void;
sendTestResult(trId: string): void;
sendTestFixtureResult(tfrId: string): void;
sendAttachmentFile(afId: string): void;
}
export interface Plugin {
start?(context: PluginContext, store: AllureStore, realtime: Realtime): Promise<void>;
start?(context: PluginContext, store: AllureStore, realtime: RealtimeSubscriber): Promise<void>;
update?(context: PluginContext, store: AllureStore): Promise<void>;

@@ -54,0 +78,0 @@ done?(context: PluginContext, store: AllureStore): Promise<void>;

@@ -1,44 +0,35 @@

import type { AllureStore } from "./store.js";
export type QualityGateRules = Record<string, any>;
export type QualityGateRulesBaseMeta<T> = {
type: T;
import type { KnownTestFailure, TestResult } from "@allurereport/core-api";
export type QualityGateValidationResult = {
success: boolean;
expected: any;
actual: any;
rule: string;
message: string;
};
export type QualityGateLabelsRulesMeta = QualityGateRulesBaseMeta<"label"> & {
name: string;
value: string;
export type QualityGateRules = Record<string, any> & {
id?: string;
fastFail?: boolean;
filter?: (tr: TestResult) => boolean;
};
export type QualityGateParametersRulesMeta = QualityGateRulesBaseMeta<"parameter"> & {
name: string;
value: string;
export type QualityGateRuleResult = {
success: boolean;
expected: any;
actual: any;
};
export type QualityGateLabelsEnforceConfig = {
type: "label";
name: string;
value: string;
rules: QualityGateRules;
};
export type QualityGateParametersEnforceConfig = {
type: "parameter";
name: string;
value: string;
rules: QualityGateRules;
};
export type QualityGateRulesMeta = Omit<QualityGateLabelsRulesMeta, "rules"> | Omit<QualityGateParametersRulesMeta, "rules">;
export type QualityGateEnforceConfig = QualityGateLabelsEnforceConfig | QualityGateParametersEnforceConfig;
export type QualityGateValidationResult = {
success: boolean;
export type QualityGateRule<T = any> = {
rule: string;
meta?: QualityGateRulesMeta;
expected?: number;
actual?: number;
message?: string;
message: (payload: {
expected: T;
actual: T;
}) => string;
validate: (payload: {
expected: T;
trs: TestResult[];
knownIssues: KnownTestFailure[];
state?: T;
}) => Promise<QualityGateRuleResult>;
};
export interface QualityGateValidator {
validate(store: AllureStore): Promise<QualityGateValidationResult>;
}
export type QualityGateValidatorConstructor = new (limit: number, meta?: QualityGateRulesMeta) => QualityGateValidator;
export type QualityGateConfig = {
rules?: QualityGateRules;
enforce?: QualityGateEnforceConfig[];
validators?: Record<string, QualityGateValidatorConstructor>;
rules?: QualityGateRules[];
use?: QualityGateRule[];
};

@@ -1,2 +0,4 @@

import type { AttachmentLink, HistoryDataPoint, HistoryTestResult, KnownTestFailure, Statistic, TestCase, TestEnvGroup, TestFixtureResult, TestResult } from "@allurereport/core-api";
import type { AttachmentLink, HistoryDataPoint, HistoryTestResult, KnownTestFailure, Statistic, TestCase, TestEnvGroup, TestError, TestFixtureResult, TestResult } from "@allurereport/core-api";
import type { ExitCode } from "./plugin.js";
import type { QualityGateValidationResult } from "./qualityGate.js";
import type { ResultFile } from "./resultFile.js";

@@ -15,2 +17,6 @@ export type TestResultFilter = (testResult: TestResult) => boolean;

allNewTestResults: () => Promise<TestResult[]>;
qualityGateResults: () => Promise<QualityGateValidationResult[]>;
globalExitCode: () => Promise<ExitCode | undefined>;
allGlobalErrors: () => Promise<TestError[]>;
allGlobalAttachments: () => Promise<AttachmentLink[]>;
testCaseById: (tcId: string) => Promise<TestCase | undefined>;

@@ -17,0 +23,0 @@ testResultById: (trId: string) => Promise<TestResult | undefined>;

{
"name": "@allurereport/plugin-api",
"version": "3.0.0-beta.17",
"version": "3.0.0-beta.18",
"description": "Allure Plugin API",

@@ -29,3 +29,3 @@ "keywords": [

"dependencies": {
"@allurereport/core-api": "3.0.0-beta.17"
"@allurereport/core-api": "3.0.0-beta.18"
},

@@ -40,3 +40,3 @@ "devDependencies": {

"@vitest/snapshot": "^2.1.9",
"allure-vitest": "^3.3.0",
"allure-vitest": "^3.3.3",
"eslint": "^8.57.0",

@@ -43,0 +43,0 @@ "eslint-config-prettier": "^9.1.0",