@callstack/reassure-compare
Advanced tools
Comparing version 1.2.1 to 1.3.0
@@ -22,8 +22,6 @@ "use strict"; | ||
/** | ||
* Duration threshold (in ms) for treating given difference as significant. | ||
* | ||
* Duration threshold (in %) for treating given difference as significant. | ||
* This is additional filter, in addition to probability threshold above. | ||
* Too small duration difference might be result of measurement grain of 1 ms. | ||
*/ | ||
const DURATION_DIFF_THRESHOLD_SIGNIFICANT = 4; | ||
const MIN_SIGNIFICANT_PERCENT_DURATION_THRESHOLD = 0.05; // 5% | ||
@@ -169,3 +167,3 @@ /** | ||
const prob = computeProbability(z); | ||
const isDurationDiffSignificant = prob < PROBABILITY_CONSIDERED_SIGNIFICANT && Math.abs(durationDiff) >= DURATION_DIFF_THRESHOLD_SIGNIFICANT; | ||
const isDurationDiffSignificant = prob < PROBABILITY_CONSIDERED_SIGNIFICANT && Math.abs(relativeDurationDiff) >= MIN_SIGNIFICANT_PERCENT_DURATION_THRESHOLD; | ||
return { | ||
@@ -172,0 +170,0 @@ name, |
@@ -6,17 +6,13 @@ "use strict"; | ||
}); | ||
exports.writeToMarkdown = void 0; | ||
exports.writeToMarkdown = writeToMarkdown; | ||
var fs = _interopRequireWildcard(require("fs/promises")); | ||
var path = _interopRequireWildcard(require("path")); | ||
var _markdownTable = _interopRequireDefault(require("markdown-table")); | ||
var md = _interopRequireWildcard(require("ts-markdown-builder")); | ||
var logger = _interopRequireWildcard(require("@callstack/reassure-logger")); | ||
var _format = require("../utils/format"); | ||
var _markdown = _interopRequireWildcard(require("../utils/markdown")); | ||
var md = _markdown; | ||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } | ||
var _markdown = require("../utils/markdown"); | ||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } | ||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } | ||
// @ts-ignore | ||
const tableHeader = ['Name', 'Type', 'Duration', 'Count']; | ||
const writeToMarkdown = async (filePath, data) => { | ||
async function writeToMarkdown(filePath, data) { | ||
try { | ||
@@ -29,4 +25,3 @@ const markdown = buildMarkdown(data); | ||
} | ||
}; | ||
exports.writeToMarkdown = writeToMarkdown; | ||
} | ||
async function writeToFile(filePath, content) { | ||
@@ -45,23 +40,26 @@ try { | ||
function buildMarkdown(data) { | ||
let result = md.heading1('Performance Comparison Report'); | ||
result += `\n${buildMetadataMarkdown('Current', data.metadata.current)}`; | ||
result += `\n${buildMetadataMarkdown('Baseline', data.metadata.baseline)}`; | ||
let doc = [md.heading('Performance Comparison Report', { | ||
level: 1 | ||
}), md.list([`${md.bold('Current')}: ${(0, _format.formatMetadata)(data.metadata.current)}`, `${md.bold('Baseline')}: ${(0, _format.formatMetadata)(data.metadata.baseline)}`])]; | ||
if (data.errors?.length) { | ||
result += `\n\n${md.heading3('Errors')}\n`; | ||
data.errors.forEach(message => { | ||
result += ` 1. 🛑 ${message}\n`; | ||
}); | ||
doc = [...doc, | ||
// | ||
md.heading('Errors', { | ||
level: 2 | ||
}), md.list(data.errors.map(text => `🛑 ${text}`))]; | ||
} | ||
if (data.warnings?.length) { | ||
result += `\n\n${md.heading3('Warnings')}\n`; | ||
data.warnings.forEach(message => { | ||
result += ` 1. 🟡 ${message}\n`; | ||
}); | ||
doc = [...doc, | ||
// | ||
md.heading('Warnings', { | ||
level: 2 | ||
}), md.list(data.warnings.map(text => `🟡 ${text}`))]; | ||
} | ||
result += `\n\n${md.heading3('Significant Changes To Duration')}`; | ||
result += `\n${buildSummaryTable(data.significant)}`; | ||
result += `\n${buildDetailsTable(data.significant)}`; | ||
result += `\n\n${md.heading3('Meaningless Changes To Duration')}`; | ||
result += `\n${buildSummaryTable(data.meaningless, true)}`; | ||
result += `\n${buildDetailsTable(data.meaningless)}`; | ||
doc = [...doc, md.heading('Significant Changes To Duration', { | ||
level: 3 | ||
}), buildSummaryTable(data.significant), buildDetailsTable(data.significant), md.heading('Meaningless Changes To Duration', { | ||
level: 3 | ||
}), buildSummaryTable(data.meaningless, { | ||
open: false | ||
}), buildDetailsTable(data.meaningless)]; | ||
@@ -72,25 +70,23 @@ // Skip renders counts if user only has function measurements | ||
if (hasRenderEntries) { | ||
result += `\n\n${md.heading3('Render Count Changes')}`; | ||
result += `\n${buildSummaryTable(data.countChanged)}`; | ||
result += `\n${buildDetailsTable(data.countChanged)}`; | ||
result += `\n\n${md.heading3('Render Issues')}`; | ||
result += `\n${buildRenderIssuesTable(data.renderIssues)}`; | ||
doc = [...doc, md.heading('Render Count Changes', { | ||
level: 3 | ||
}), buildSummaryTable(data.countChanged), buildDetailsTable(data.countChanged), md.heading('Render Issues', { | ||
level: 3 | ||
}), buildRenderIssuesTable(data.renderIssues)]; | ||
} | ||
result += `\n\n${md.heading3('Added Scenarios')}`; | ||
result += `\n${buildSummaryTable(data.added)}`; | ||
result += `\n${buildDetailsTable(data.added)}`; | ||
result += `\n\n${md.heading3('Removed Scenarios')}`; | ||
result += `\n${buildSummaryTable(data.removed)}`; | ||
result += `\n${buildDetailsTable(data.removed)}`; | ||
result += '\n'; | ||
return result; | ||
doc = [...doc, md.heading('Added Entries', { | ||
level: 3 | ||
}), buildSummaryTable(data.added), buildDetailsTable(data.added), md.heading('Removed Entries', { | ||
level: 3 | ||
}), buildSummaryTable(data.removed), buildDetailsTable(data.removed)]; | ||
return md.joinBlocks(doc); | ||
} | ||
function buildMetadataMarkdown(name, metadata) { | ||
return ` - ${md.bold(name)}: ${(0, _format.formatMetadata)(metadata)}`; | ||
} | ||
function buildSummaryTable(entries, collapse = false) { | ||
function buildSummaryTable(entries, options) { | ||
if (!entries.length) return md.italic('There are no entries'); | ||
const open = options?.open ?? true; | ||
const rows = entries.map(entry => [entry.name, entry.type, formatEntryDuration(entry), formatEntryCount(entry)]); | ||
const content = (0, _markdownTable.default)([tableHeader, ...rows]); | ||
return collapse ? (0, _markdown.collapsibleSection)('Show entries', content) : content; | ||
const tableContent = md.table(tableHeader, rows); | ||
return md.disclosure('Show entries', tableContent, { | ||
open | ||
}); | ||
} | ||
@@ -100,30 +96,29 @@ function buildDetailsTable(entries) { | ||
const rows = entries.map(entry => [entry.name, entry.type, buildDurationDetailsEntry(entry), buildCountDetailsEntry(entry)]); | ||
const content = (0, _markdownTable.default)([tableHeader, ...rows]); | ||
return (0, _markdown.collapsibleSection)('Show details', content); | ||
return md.disclosure('Show details', md.table(tableHeader, rows)); | ||
} | ||
function formatEntryDuration(entry) { | ||
if (entry.baseline != null && 'current' in entry) return (0, _format.formatDurationChange)(entry); | ||
if (entry.baseline != null && entry.current != null) return (0, _format.formatDurationChange)(entry); | ||
if (entry.baseline != null) return (0, _format.formatDuration)(entry.baseline.meanDuration); | ||
if ('current' in entry) return (0, _format.formatDuration)(entry.current.meanDuration); | ||
if (entry.current != null) return (0, _format.formatDuration)(entry.current.meanDuration); | ||
return ''; | ||
} | ||
function formatEntryCount(entry) { | ||
if (entry.baseline != null && 'current' in entry) return (0, _format.formatCountChange)(entry.current.meanCount, entry.baseline.meanCount); | ||
if (entry.baseline != null && entry.current != null) return (0, _format.formatCountChange)(entry.current.meanCount, entry.baseline.meanCount); | ||
if (entry.baseline != null) return (0, _format.formatCount)(entry.baseline.meanCount); | ||
if ('current' in entry) return (0, _format.formatCount)(entry.current.meanCount); | ||
if (entry.current != null) return (0, _format.formatCount)(entry.current.meanCount); | ||
return ''; | ||
} | ||
function buildDurationDetailsEntry(entry) { | ||
return [entry.baseline != null ? buildDurationDetails('Baseline', entry.baseline) : '', 'current' in entry ? buildDurationDetails('Current', entry.current) : ''].filter(Boolean).join('<br/><br/>'); | ||
return md.joinBlocks([entry.baseline != null ? buildDurationDetails('Baseline', entry.baseline) : '', entry.current != null ? buildDurationDetails('Current', entry.current) : '']); | ||
} | ||
function buildCountDetailsEntry(entry) { | ||
return [entry.baseline != null ? buildCountDetails('Baseline', entry.baseline) : '', 'current' in entry ? buildCountDetails('Current', entry.current) : ''].filter(Boolean).join('<br/><br/>'); | ||
return md.joinBlocks([entry.baseline != null ? buildCountDetails('Baseline', entry.baseline) : '', entry.current != null ? buildCountDetails('Current', entry.current) : '']); | ||
} | ||
function buildDurationDetails(title, entry) { | ||
const relativeStdev = entry.stdevDuration / entry.meanDuration; | ||
return [md.bold(title), `Mean: ${(0, _format.formatDuration)(entry.meanDuration)}`, `Stdev: ${(0, _format.formatDuration)(entry.stdevDuration)} (${(0, _format.formatPercent)(relativeStdev)})`, entry.durations ? `Runs: ${formatRunDurations(entry.durations)}` : '', entry.warmupDurations ? `Warmup runs: ${formatRunDurations(entry.warmupDurations)}` : ''].filter(Boolean).join(`<br/>`); | ||
return (0, _markdown.joinLines)([md.bold(title), `Mean: ${(0, _format.formatDuration)(entry.meanDuration)}`, `Stdev: ${(0, _format.formatDuration)(entry.stdevDuration)} (${(0, _format.formatPercent)(relativeStdev)})`, entry.durations ? `Runs: ${formatRunDurations(entry.durations)}` : '', entry.warmupDurations ? `Warmup runs: ${formatRunDurations(entry.warmupDurations)}` : '']); | ||
} | ||
function buildCountDetails(title, entry) { | ||
const relativeStdev = entry.stdevCount / entry.meanCount; | ||
return [md.bold(title), `Mean: ${(0, _format.formatCount)(entry.meanCount)}`, `Stdev: ${(0, _format.formatCount)(entry.stdevCount)} (${(0, _format.formatPercent)(relativeStdev)})`, entry.counts ? `Runs: ${entry.counts.map(_format.formatCount).join(' ')}` : '', buildRenderIssuesList(entry.issues)].filter(Boolean).join(`<br/>`); | ||
return (0, _markdown.joinLines)([md.bold(title), `Mean: ${(0, _format.formatCount)(entry.meanCount)}`, `Stdev: ${(0, _format.formatCount)(entry.stdevCount)} (${(0, _format.formatPercent)(relativeStdev)})`, entry.counts ? `Runs: ${entry.counts.map(_format.formatCount).join(' ')}` : '', buildRenderIssuesList(entry.issues)]); | ||
} | ||
@@ -137,3 +132,3 @@ function formatRunDurations(values) { | ||
const rows = entries.map(entry => [entry.name, formatInitialUpdates(entry.current.issues?.initialUpdateCount), formatRedundantUpdates(entry.current.issues?.redundantUpdates)]); | ||
return (0, _markdownTable.default)([tableHeader, ...rows]); | ||
return md.table(tableHeader, rows); | ||
} | ||
@@ -144,8 +139,8 @@ function buildRenderIssuesList(issues) { | ||
if (issues?.initialUpdateCount) { | ||
output.push(` - Initial updates: ${formatInitialUpdates(issues.initialUpdateCount, false)}`); | ||
output.push(`- Initial updates: ${formatInitialUpdates(issues.initialUpdateCount, false)}`); | ||
} | ||
if (issues?.redundantUpdates?.length) { | ||
output.push(` - Redundant updates: ${formatRedundantUpdates(issues.redundantUpdates, false)}`); | ||
output.push(`- Redundant updates: ${formatRedundantUpdates(issues.redundantUpdates, false)}`); | ||
} | ||
return output.join('<br/>'); | ||
return output.join('\n'); | ||
} | ||
@@ -152,0 +147,0 @@ function formatInitialUpdates(count, showSymbol = true) { |
@@ -6,26 +6,13 @@ "use strict"; | ||
}); | ||
exports.bold = bold; | ||
exports.collapsibleSection = collapsibleSection; | ||
exports.heading1 = heading1; | ||
exports.heading2 = heading2; | ||
exports.heading3 = heading3; | ||
exports.italic = italic; | ||
function heading1(text) { | ||
return `# ${text}\n`; | ||
exports.joinLines = joinLines; | ||
var _tsMarkdownBuilder = require("ts-markdown-builder"); | ||
/** | ||
* Join lines of text into a single paragraph string with line breaks. | ||
* | ||
* @param lines - The lines of text to join. | ||
* @returns Paragraph string. | ||
*/ | ||
function joinLines(lines) { | ||
return lines.filter(Boolean).join(_tsMarkdownBuilder.lineBreak); | ||
} | ||
function heading2(text) { | ||
return `## ${text}\n`; | ||
} | ||
function heading3(text) { | ||
return `### ${text}\n`; | ||
} | ||
function bold(text) { | ||
return `**${text}**`; | ||
} | ||
function italic(text) { | ||
return `*${text}*`; | ||
} | ||
function collapsibleSection(title, content) { | ||
return `<details>\n<summary>${title}</summary>\n\n${content}\n</details>\n\n`; | ||
} | ||
//# sourceMappingURL=markdown.js.map |
@@ -14,8 +14,6 @@ import * as fsSync from 'fs'; | ||
/** | ||
* Duration threshold (in ms) for treating given difference as significant. | ||
* | ||
* Duration threshold (in %) for treating given difference as significant. | ||
* This is additional filter, in addition to probability threshold above. | ||
* Too small duration difference might be result of measurement grain of 1 ms. | ||
*/ | ||
const DURATION_DIFF_THRESHOLD_SIGNIFICANT = 4; | ||
const MIN_SIGNIFICANT_PERCENT_DURATION_THRESHOLD = 0.05; // 5% | ||
@@ -161,3 +159,3 @@ /** | ||
const prob = computeProbability(z); | ||
const isDurationDiffSignificant = prob < PROBABILITY_CONSIDERED_SIGNIFICANT && Math.abs(durationDiff) >= DURATION_DIFF_THRESHOLD_SIGNIFICANT; | ||
const isDurationDiffSignificant = prob < PROBABILITY_CONSIDERED_SIGNIFICANT && Math.abs(relativeDurationDiff) >= MIN_SIGNIFICANT_PERCENT_DURATION_THRESHOLD; | ||
return { | ||
@@ -164,0 +162,0 @@ name, |
import * as fs from 'fs/promises'; | ||
import * as path from 'path'; | ||
// @ts-ignore | ||
import markdownTable from 'markdown-table'; | ||
import * as md from 'ts-markdown-builder'; | ||
import * as logger from '@callstack/reassure-logger'; | ||
import { formatCount, formatDuration, formatMetadata, formatPercent, formatCountChange, formatDurationChange } from '../utils/format'; | ||
import * as md from '../utils/markdown'; | ||
import { collapsibleSection } from '../utils/markdown'; | ||
import { joinLines } from '../utils/markdown'; | ||
const tableHeader = ['Name', 'Type', 'Duration', 'Count']; | ||
export const writeToMarkdown = async (filePath, data) => { | ||
export async function writeToMarkdown(filePath, data) { | ||
try { | ||
@@ -18,3 +16,3 @@ const markdown = buildMarkdown(data); | ||
} | ||
}; | ||
} | ||
async function writeToFile(filePath, content) { | ||
@@ -33,23 +31,26 @@ try { | ||
function buildMarkdown(data) { | ||
let result = md.heading1('Performance Comparison Report'); | ||
result += `\n${buildMetadataMarkdown('Current', data.metadata.current)}`; | ||
result += `\n${buildMetadataMarkdown('Baseline', data.metadata.baseline)}`; | ||
let doc = [md.heading('Performance Comparison Report', { | ||
level: 1 | ||
}), md.list([`${md.bold('Current')}: ${formatMetadata(data.metadata.current)}`, `${md.bold('Baseline')}: ${formatMetadata(data.metadata.baseline)}`])]; | ||
if (data.errors?.length) { | ||
result += `\n\n${md.heading3('Errors')}\n`; | ||
data.errors.forEach(message => { | ||
result += ` 1. 🛑 ${message}\n`; | ||
}); | ||
doc = [...doc, | ||
// | ||
md.heading('Errors', { | ||
level: 2 | ||
}), md.list(data.errors.map(text => `🛑 ${text}`))]; | ||
} | ||
if (data.warnings?.length) { | ||
result += `\n\n${md.heading3('Warnings')}\n`; | ||
data.warnings.forEach(message => { | ||
result += ` 1. 🟡 ${message}\n`; | ||
}); | ||
doc = [...doc, | ||
// | ||
md.heading('Warnings', { | ||
level: 2 | ||
}), md.list(data.warnings.map(text => `🟡 ${text}`))]; | ||
} | ||
result += `\n\n${md.heading3('Significant Changes To Duration')}`; | ||
result += `\n${buildSummaryTable(data.significant)}`; | ||
result += `\n${buildDetailsTable(data.significant)}`; | ||
result += `\n\n${md.heading3('Meaningless Changes To Duration')}`; | ||
result += `\n${buildSummaryTable(data.meaningless, true)}`; | ||
result += `\n${buildDetailsTable(data.meaningless)}`; | ||
doc = [...doc, md.heading('Significant Changes To Duration', { | ||
level: 3 | ||
}), buildSummaryTable(data.significant), buildDetailsTable(data.significant), md.heading('Meaningless Changes To Duration', { | ||
level: 3 | ||
}), buildSummaryTable(data.meaningless, { | ||
open: false | ||
}), buildDetailsTable(data.meaningless)]; | ||
@@ -60,25 +61,23 @@ // Skip renders counts if user only has function measurements | ||
if (hasRenderEntries) { | ||
result += `\n\n${md.heading3('Render Count Changes')}`; | ||
result += `\n${buildSummaryTable(data.countChanged)}`; | ||
result += `\n${buildDetailsTable(data.countChanged)}`; | ||
result += `\n\n${md.heading3('Render Issues')}`; | ||
result += `\n${buildRenderIssuesTable(data.renderIssues)}`; | ||
doc = [...doc, md.heading('Render Count Changes', { | ||
level: 3 | ||
}), buildSummaryTable(data.countChanged), buildDetailsTable(data.countChanged), md.heading('Render Issues', { | ||
level: 3 | ||
}), buildRenderIssuesTable(data.renderIssues)]; | ||
} | ||
result += `\n\n${md.heading3('Added Scenarios')}`; | ||
result += `\n${buildSummaryTable(data.added)}`; | ||
result += `\n${buildDetailsTable(data.added)}`; | ||
result += `\n\n${md.heading3('Removed Scenarios')}`; | ||
result += `\n${buildSummaryTable(data.removed)}`; | ||
result += `\n${buildDetailsTable(data.removed)}`; | ||
result += '\n'; | ||
return result; | ||
doc = [...doc, md.heading('Added Entries', { | ||
level: 3 | ||
}), buildSummaryTable(data.added), buildDetailsTable(data.added), md.heading('Removed Entries', { | ||
level: 3 | ||
}), buildSummaryTable(data.removed), buildDetailsTable(data.removed)]; | ||
return md.joinBlocks(doc); | ||
} | ||
function buildMetadataMarkdown(name, metadata) { | ||
return ` - ${md.bold(name)}: ${formatMetadata(metadata)}`; | ||
} | ||
function buildSummaryTable(entries, collapse = false) { | ||
function buildSummaryTable(entries, options) { | ||
if (!entries.length) return md.italic('There are no entries'); | ||
const open = options?.open ?? true; | ||
const rows = entries.map(entry => [entry.name, entry.type, formatEntryDuration(entry), formatEntryCount(entry)]); | ||
const content = markdownTable([tableHeader, ...rows]); | ||
return collapse ? collapsibleSection('Show entries', content) : content; | ||
const tableContent = md.table(tableHeader, rows); | ||
return md.disclosure('Show entries', tableContent, { | ||
open | ||
}); | ||
} | ||
@@ -88,30 +87,29 @@ function buildDetailsTable(entries) { | ||
const rows = entries.map(entry => [entry.name, entry.type, buildDurationDetailsEntry(entry), buildCountDetailsEntry(entry)]); | ||
const content = markdownTable([tableHeader, ...rows]); | ||
return collapsibleSection('Show details', content); | ||
return md.disclosure('Show details', md.table(tableHeader, rows)); | ||
} | ||
function formatEntryDuration(entry) { | ||
if (entry.baseline != null && 'current' in entry) return formatDurationChange(entry); | ||
if (entry.baseline != null && entry.current != null) return formatDurationChange(entry); | ||
if (entry.baseline != null) return formatDuration(entry.baseline.meanDuration); | ||
if ('current' in entry) return formatDuration(entry.current.meanDuration); | ||
if (entry.current != null) return formatDuration(entry.current.meanDuration); | ||
return ''; | ||
} | ||
function formatEntryCount(entry) { | ||
if (entry.baseline != null && 'current' in entry) return formatCountChange(entry.current.meanCount, entry.baseline.meanCount); | ||
if (entry.baseline != null && entry.current != null) return formatCountChange(entry.current.meanCount, entry.baseline.meanCount); | ||
if (entry.baseline != null) return formatCount(entry.baseline.meanCount); | ||
if ('current' in entry) return formatCount(entry.current.meanCount); | ||
if (entry.current != null) return formatCount(entry.current.meanCount); | ||
return ''; | ||
} | ||
function buildDurationDetailsEntry(entry) { | ||
return [entry.baseline != null ? buildDurationDetails('Baseline', entry.baseline) : '', 'current' in entry ? buildDurationDetails('Current', entry.current) : ''].filter(Boolean).join('<br/><br/>'); | ||
return md.joinBlocks([entry.baseline != null ? buildDurationDetails('Baseline', entry.baseline) : '', entry.current != null ? buildDurationDetails('Current', entry.current) : '']); | ||
} | ||
function buildCountDetailsEntry(entry) { | ||
return [entry.baseline != null ? buildCountDetails('Baseline', entry.baseline) : '', 'current' in entry ? buildCountDetails('Current', entry.current) : ''].filter(Boolean).join('<br/><br/>'); | ||
return md.joinBlocks([entry.baseline != null ? buildCountDetails('Baseline', entry.baseline) : '', entry.current != null ? buildCountDetails('Current', entry.current) : '']); | ||
} | ||
function buildDurationDetails(title, entry) { | ||
const relativeStdev = entry.stdevDuration / entry.meanDuration; | ||
return [md.bold(title), `Mean: ${formatDuration(entry.meanDuration)}`, `Stdev: ${formatDuration(entry.stdevDuration)} (${formatPercent(relativeStdev)})`, entry.durations ? `Runs: ${formatRunDurations(entry.durations)}` : '', entry.warmupDurations ? `Warmup runs: ${formatRunDurations(entry.warmupDurations)}` : ''].filter(Boolean).join(`<br/>`); | ||
return joinLines([md.bold(title), `Mean: ${formatDuration(entry.meanDuration)}`, `Stdev: ${formatDuration(entry.stdevDuration)} (${formatPercent(relativeStdev)})`, entry.durations ? `Runs: ${formatRunDurations(entry.durations)}` : '', entry.warmupDurations ? `Warmup runs: ${formatRunDurations(entry.warmupDurations)}` : '']); | ||
} | ||
function buildCountDetails(title, entry) { | ||
const relativeStdev = entry.stdevCount / entry.meanCount; | ||
return [md.bold(title), `Mean: ${formatCount(entry.meanCount)}`, `Stdev: ${formatCount(entry.stdevCount)} (${formatPercent(relativeStdev)})`, entry.counts ? `Runs: ${entry.counts.map(formatCount).join(' ')}` : '', buildRenderIssuesList(entry.issues)].filter(Boolean).join(`<br/>`); | ||
return joinLines([md.bold(title), `Mean: ${formatCount(entry.meanCount)}`, `Stdev: ${formatCount(entry.stdevCount)} (${formatPercent(relativeStdev)})`, entry.counts ? `Runs: ${entry.counts.map(formatCount).join(' ')}` : '', buildRenderIssuesList(entry.issues)]); | ||
} | ||
@@ -125,3 +123,3 @@ function formatRunDurations(values) { | ||
const rows = entries.map(entry => [entry.name, formatInitialUpdates(entry.current.issues?.initialUpdateCount), formatRedundantUpdates(entry.current.issues?.redundantUpdates)]); | ||
return markdownTable([tableHeader, ...rows]); | ||
return md.table(tableHeader, rows); | ||
} | ||
@@ -132,8 +130,8 @@ function buildRenderIssuesList(issues) { | ||
if (issues?.initialUpdateCount) { | ||
output.push(` - Initial updates: ${formatInitialUpdates(issues.initialUpdateCount, false)}`); | ||
output.push(`- Initial updates: ${formatInitialUpdates(issues.initialUpdateCount, false)}`); | ||
} | ||
if (issues?.redundantUpdates?.length) { | ||
output.push(` - Redundant updates: ${formatRedundantUpdates(issues.redundantUpdates, false)}`); | ||
output.push(`- Redundant updates: ${formatRedundantUpdates(issues.redundantUpdates, false)}`); | ||
} | ||
return output.join('<br/>'); | ||
return output.join('\n'); | ||
} | ||
@@ -140,0 +138,0 @@ function formatInitialUpdates(count, showSymbol = true) { |
@@ -1,19 +0,12 @@ | ||
export function heading1(text) { | ||
return `# ${text}\n`; | ||
import { lineBreak } from 'ts-markdown-builder'; | ||
/** | ||
* Join lines of text into a single paragraph string with line breaks. | ||
* | ||
* @param lines - The lines of text to join. | ||
* @returns Paragraph string. | ||
*/ | ||
export function joinLines(lines) { | ||
return lines.filter(Boolean).join(lineBreak); | ||
} | ||
export function heading2(text) { | ||
return `## ${text}\n`; | ||
} | ||
export function heading3(text) { | ||
return `### ${text}\n`; | ||
} | ||
export function bold(text) { | ||
return `**${text}**`; | ||
} | ||
export function italic(text) { | ||
return `*${text}*`; | ||
} | ||
export function collapsibleSection(title, content) { | ||
return `<details>\n<summary>${title}</summary>\n\n${content}\n</details>\n\n`; | ||
} | ||
//# sourceMappingURL=markdown.js.map |
import type { CompareResult } from '../types'; | ||
export declare const writeToMarkdown: (filePath: string, data: CompareResult) => Promise<void>; | ||
export declare function writeToMarkdown(filePath: string, data: CompareResult): Promise<void>; | ||
//# sourceMappingURL=markdown.d.ts.map |
@@ -43,2 +43,3 @@ /** Parsed performance results file. */ | ||
baseline: MeasureEntry; | ||
current?: undefined; | ||
} | ||
@@ -45,0 +46,0 @@ export interface CompareMetadata { |
@@ -1,7 +0,8 @@ | ||
export declare function heading1(text: string): string; | ||
export declare function heading2(text: string): string; | ||
export declare function heading3(text: string): string; | ||
export declare function bold(text: string): string; | ||
export declare function italic(text: string): string; | ||
export declare function collapsibleSection(title: string, content: string): string; | ||
/** | ||
* Join lines of text into a single paragraph string with line breaks. | ||
* | ||
* @param lines - The lines of text to join. | ||
* @returns Paragraph string. | ||
*/ | ||
export declare function joinLines(lines: string[]): string; | ||
//# sourceMappingURL=markdown.d.ts.map |
{ | ||
"name": "@callstack/reassure-compare", | ||
"version": "1.2.1", | ||
"version": "1.3.0", | ||
"description": "Performance testing companion for React and React Native", | ||
@@ -38,4 +38,4 @@ "main": "lib/commonjs/index.js", | ||
"dependencies": { | ||
"@callstack/reassure-logger": "1.2.1", | ||
"markdown-table": "^2.0.0", | ||
"@callstack/reassure-logger": "1.3.0", | ||
"ts-markdown-builder": "0.4.0", | ||
"ts-regex-builder": "^1.8.2", | ||
@@ -42,0 +42,0 @@ "zod": "^3.23.8" |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
172046
1666
+ Addedts-markdown-builder@0.4.0
+ Added@callstack/reassure-logger@1.3.0(transitive)
+ Addedts-markdown-builder@0.4.0(transitive)
- Removedmarkdown-table@^2.0.0
- Removed@callstack/reassure-logger@1.2.1(transitive)
- Removedmarkdown-table@2.0.0(transitive)
- Removedrepeat-string@1.6.1(transitive)