tests/tst_cost_presentation.qml
import QtQuick
import QtTest
import "../contents/ui/CostPresentation.js" as CostPresentation
TestCase {
name: "CostPresentation"
function test_barCanvasCoordinatesStayFiniteForMissingDimensions() {
var coordinates = []
function record() {
for (var i = 0; i < arguments.length; i++)
coordinates.push(arguments[i])
}
var context = {
beginPath: function() {}, closePath: function() {}, fill: function() {},
moveTo: record, lineTo: record, quadraticCurveTo: record
}
CostPresentation.paintRoundedTopBar(context, 5, 100, Number.NaN, undefined, 3)
CostPresentation.paintRoundedTopBar(context, 5, 100, Infinity, 20, 3)
CostPresentation.paintRoundedTopBar(context, 5, 100, 10, Infinity, 3)
verify(coordinates.length > 0)
for (var coordinate of coordinates)
verify(isFinite(coordinate), "Canvas coordinates must remain finite")
}
function test_costDayIndexAfterRefresh_data() {
var first = { label: "2026-09-01", sourceIndex: 0 }
var second = { label: "2026-09-02", sourceIndex: 1 }
return [
{ tag: "same-days-new-objects", previous: [first, second], index: 1,
next: [{ label: first.label }, { label: second.label }], expected: 1 },
{ tag: "day-moved", previous: [first, second], index: 1,
next: [second, first], expected: 0 },
{ tag: "earlier-day-removed", previous: [first, second], index: 1,
next: [second], expected: 0 },
{ tag: "selected-day-removed", previous: [first, second], index: 0,
next: [second], expected: -1 },
{ tag: "no-selection", previous: [first], index: -1, next: [first], expected: -1 },
{ tag: "empty-refresh", previous: [first], index: 0, next: [], expected: -1 },
{ tag: "missing-date", previous: [{}], index: 0, next: [{}], expected: -1 },
{ tag: "duplicate-date", previous: [first], index: 0, next: [first, first], expected: -1 },
{ tag: "ambiguous-old-date", previous: [first, first], index: 0, next: [first], expected: -1 },
{ tag: "invalid-index", previous: [first], index: 0.5, next: [first], expected: -1 },
{ tag: "string-index", previous: [first], index: "0", next: [first], expected: -1 },
{ tag: "out-of-range", previous: [first], index: 1, next: [first], expected: -1 },
{ tag: "missing-old-points", previous: null, index: 0, next: [first], expected: -1 },
{ tag: "missing-new-points", previous: [first], index: 0, next: null, expected: -1 },
{ tag: "null-point", previous: [null], index: 0, next: [first], expected: -1 },
{ tag: "non-text-date", previous: [{ label: 1 }], index: 0, next: [{ label: 1 }], expected: -1 }
]
}
function test_costDayIndexAfterRefresh(data) {
compare(CostPresentation.costDayIndexAfterRefresh(data.previous, data.index, data.next), data.expected)
}
function test_selectedCostDayUsesSourceRowAfterUnavailableAmountsAreSkipped() {
var daily = [
{ label: "2026-09-01", cost: null, tokens: 3, models: [{label: "First"}] },
{ label: "2026-09-02", cost: 0, tokens: 7, models: [{label: "Second"}] }
]
var costPoints = CostPresentation.chartPoints(fmt, daily, false)
compare(costPoints.length, 1)
compare(CostPresentation.selectedCostDay(daily, costPoints, 0), daily[1])
var tokenPoints = CostPresentation.chartPoints(fmt, daily, true)
compare(CostPresentation.selectedCostDay(daily, tokenPoints, 0), daily[0])
compare(CostPresentation.selectedCostDay(daily, tokenPoints, 1), daily[1])
compare(CostPresentation.selectedCostDay(daily, costPoints, -1), null)
compare(CostPresentation.selectedCostDay([], costPoints, 0), null)
compare(CostPresentation.selectedCostDay(daily, [{ sourceIndex: "1" }], 0), null)
compare(CostPresentation.selectedCostDay(daily, [{ sourceIndex: 0.5 }], 0), null)
compare(CostPresentation.selectedCostDay(daily, costPoints, 0.5), null)
compare(CostPresentation.selectedCostDay(daily, null, 0), null)
}
function test_amountSummaryPreservesAvailableMetrics() {
var fmt = CostPresentation.numberFormat(",", ".")
var tokensText = function(tokens) { return tokens + " tokens" }
compare(CostPresentation.amountSummary(fmt, { cost: null, tokens: 5 }, tokensText), "5 tokens")
compare(CostPresentation.amountSummary(fmt, { cost: 0, tokens: null, currency: "USD" }, tokensText), "$0.00")
compare(CostPresentation.amountSummary(fmt, { cost: 0, tokens: 0, currency: "USD" }, tokensText), "$0.00 · 0 tokens")
compare(CostPresentation.amountSummary(fmt, null, tokensText), "-")
}
function test_modelRowsDistinguishZeroFromMissingAmounts() {
var rows = CostPresentation.modelRows(fmt, { models: [
{ label: "Free", cost: 0, tokens: 2, currency: "USD" },
{ label: "Unpriced", cost: null, tokens: 2, currency: "USD" },
{ label: "Unknown tokens", cost: 1, tokens: null, currency: "USD" },
{ label: "Unknown", cost: null, tokens: null, currency: "USD" }
] }, null)
compare(rows[0].value, "$0.00 · 2")
compare(rows[1].value, "2")
compare(rows[2].value, "$1.00")
compare(rows[3].value, "-")
}
function test_projectRowsFollowProviderOrderAndSelectedMetric() {
var costs = [{ provider: "codex", projects: { rows: [
{ label: "Token heavy", cost: 1, tokens: 9000, currency: "USD" },
{ label: "Cost heavy", cost: 8, tokens: 100, currency: "USD" },
{ label: "Token only", cost: null, tokens: 500, currency: "USD" }
], truncated: false } }, { provider: "future", projects: { rows: [
{ label: "Another currency", cost: 100, tokens: 10, currency: "EUR" }
], truncated: false } }]
var money = CostPresentation.projectRows(costs, false)
compare(money.rows.map(function(row) { return row.label }),
["Cost heavy", "Token heavy", "Token only", "Another currency"])
compare(money.rows[0].provider, "codex")
compare(money.rows[2].cost, null)
compare(money.rows[3].currency, "EUR")
compare(money.truncated, false)
compare(CostPresentation.projectRows(costs, true).rows[0].label, "Token heavy")
compare(costs[0].projects.rows[0].label, "Token heavy")
}
function test_projectRowsKeepDuplicatesUnknownsAndWindowTrust() {
var snapshot = {
provider: "codex", totals: { cost: 3, tokens: 90, currency: "USD" },
trust: { sourceKind: "listPrice",
coverage: { priced: 0, estimated: 2, unpriced: 1, unmetered: 0 } },
projects: { rows: [
{ label: "Same", cost: 1, tokens: null, currency: "USD" },
{ label: "Same", cost: 2, tokens: 20, currency: "USD" },
{ label: "No price", cost: null, tokens: 70, currency: "USD" },
{ label: "Empty", cost: 0, tokens: 0, currency: "USD" }
] }
}
var money = CostPresentation.projectRows([snapshot], false).rows
compare(money.length, 4)
compare(money[0].label, "Same")
compare(money[1].label, "Same")
compare(money[0].valueMode, "partial")
compare(money[2].cost, 0)
compare(money[3].cost, null)
var tokens = CostPresentation.projectRows([snapshot], true).rows
compare(tokens[0].label, "No price")
compare(tokens[2].tokens, 0)
compare(tokens[3].tokens, null)
}
function test_projectRowsBoundTheWholePopupAndSignalOmissions() {
var rows = []
for (var i = 0; i < 128; i++) {
rows.push({ label: "Project " + i, cost: i, tokens: i, currency: "USD" })
}
var result = CostPresentation.projectRows([
{ provider: "codex", projects: { rows: rows } },
{ provider: "future", projects: { rows: rows } }
], false)
compare(result.rows.length, 128)
compare(result.rows[0].cost, 127)
compare(result.truncated, true)
compare(CostPresentation.projectRows([
{ provider: "codex", projects: { rows: [], truncated: true } }
], false).truncated, true)
compare(CostPresentation.projectRows([
{ provider: "codex", projects: { rows: rows } }
], false).truncated, false)
}
function test_projectRowsUseOnlyRangeMatchedSnapshotsAndTolerateLegacyData() {
var current = { provider: "codex", historyDays: 7, projects: { rows: [
{ label: "Current", cost: 2, tokens: 10, currency: "USD" }
] } }
var stale = { provider: "claude", historyDays: 30, projects: { rows: [
{ label: "Stale", cost: 99, tokens: 100, currency: "USD" }
] } }
var snapshots = CostPresentation.spendSnapshots({ codex: current, claude: stale }, 7)
compare(CostPresentation.projectRows(snapshots, false).rows.length, 1)
compare(CostPresentation.projectRows(snapshots, false).rows[0].label, "Current")
compare(CostPresentation.projectRows([{ provider: "legacy" }], false),
{ rows: [], truncated: false })
compare(CostPresentation.projectRows(null, false), { rows: [], truncated: false })
}
readonly property var fmt: CostPresentation.numberFormat(",", ".")
function dailyPoint(label, cost, tokens, currency) {
return { label: label, cost: cost, tokens: tokens, currency: currency || "USD" }
}
function trustedCost(currency, coverage, sourceKind) {
return {
totals: { cost: 1, tokens: 10, currency: currency || "USD" },
trust: { coverage: coverage || null, sourceKind: sourceKind || "" }
}
}
function test_numberFormatFallsBackWhenTheCallerHasNoLocale() {
var fallback = CostPresentation.numberFormat(undefined, undefined)
compare(fallback.group, ",")
compare(fallback.decimal, ".")
compare(CostPresentation.amountString(fallback, 1234.5, "USD"), "$1,234.50")
}
function test_amountStringHonoursTheCallerSeparators() {
var italian = CostPresentation.numberFormat(".", ",")
compare(CostPresentation.amountString(italian, 1234.5, "USD"), "$1.234,50")
compare(CostPresentation.amountString(fmt, 1234.5, "USD"), "$1,234.50")
}
function test_amountStringKeepsTheSignOutsideTheCurrencySymbol() {
compare(CostPresentation.amountString(fmt, -12, "USD"), "-$12.00")
compare(CostPresentation.amountString(fmt, -12, "EUR"), "-EUR 12.00")
}
function test_quotaIsACreditBalanceNotMoney() {
compare(CostPresentation.amountString(fmt, 1499.6, "Quota"), "1500")
compare(CostPresentation.amountString(fmt, 1499.6, " Quota "), "1500")
compare(CostPresentation.amountString(fmt, "abc", "Quota"), "-")
compare(CostPresentation.amountString(fmt, null, "Quota"), "-")
}
function test_nonNumericAmountDegradesToDash() {
compare(CostPresentation.amountString(fmt, "abc", "USD"), "-")
compare(CostPresentation.amountString(fmt, "abc", "EUR"), "-")
compare(CostPresentation.amountString(fmt, "12", "USD"), "-")
compare(CostPresentation.amountString(fmt, "", "USD"), "-")
compare(CostPresentation.amountString(fmt, undefined, "USD"), "-")
compare(CostPresentation.amountString(fmt, Number.NaN, "USD"), "-")
compare(CostPresentation.amountString(fmt, null, "USD"), "-")
compare(CostPresentation.amountString(fmt, false, "USD"), "-")
compare(CostPresentation.amountString(fmt, [], "USD"), "-")
compare(CostPresentation.amountString(fmt, {}, "USD"), "-")
compare(CostPresentation.groupedDecimalString(fmt, "abc", 2), "-")
}
function test_amountStringHandlesNullOrMissingFormatGracefully() {
compare(CostPresentation.amountString(null, 12, "USD"), "$12.00")
compare(CostPresentation.amountString(undefined, 12, "USD"), "$12.00")
compare(CostPresentation.amountString({}, 12, "USD"), "$12.00")
compare(CostPresentation.groupedDecimalString(null, 1234.5, 2), "1,234.50")
}
function test_amountStringHandlesEmptyOrMissingCurrencyGracefully() {
compare(CostPresentation.amountString(fmt, 12, ""), "12.00")
compare(CostPresentation.amountString(fmt, -12, ""), "-12.00")
compare(CostPresentation.amountString(fmt, 12, null), "12.00")
compare(CostPresentation.amountString(fmt, 12, undefined), "12.00")
compare(CostPresentation.amountString(fmt, 12, " "), "12.00")
}
// Number.toFixed returns exponential notation past 1e21, which has no
// fixed-point digits to group: without the guard "1e+21" gained a bogus
// separator ("1e,+21").
function test_groupedDecimalStringKeepsHugeMagnitudesReadable() {
compare(CostPresentation.groupedDecimalString(fmt, 1e21, 2), "1e+21")
compare(CostPresentation.groupedDecimalString(fmt, -1e21, 2), "1e+21")
compare(CostPresentation.groupedDecimalString(fmt, 1.5e21, 2), "1.5e+21")
compare(CostPresentation.amountString(fmt, 1e21, "USD"), "$1e+21")
compare(CostPresentation.amountString(fmt, -1e21, "USD"), "-$1e+21")
}
// Credit balances print as bare counts: whole balances keep no fractional
// part. Rounding can carry a fractional balance across the whole boundary
// (99.95 -> "100.0"), so the fractional digit drops when the rounded
// figure is whole.
function test_formatCountDropsTheFractionalDigitAfterRoundingUp() {
compare(CostPresentation.formatCount(fmt, 0), "0")
compare(CostPresentation.formatCount(fmt, 100), "100")
compare(CostPresentation.formatCount(fmt, 99.95), "100")
compare(CostPresentation.formatCount(fmt, 2.95), "3")
compare(CostPresentation.formatCount(fmt, -99.95), "-100")
compare(CostPresentation.formatCount(fmt, 99.94), "99.9")
compare(CostPresentation.formatCount(fmt, 199.99), "200")
compare(CostPresentation.formatCount(fmt, 1234.5), "1,235")
compare(CostPresentation.formatCount(fmt, 12.5), "12.5")
compare(CostPresentation.formatCount(fmt, "abc"), "-")
compare(CostPresentation.formatCount(fmt, Number.NaN), "-")
compare(CostPresentation.formatCount(fmt, undefined), "-")
// Number(null) coerces to 0, as the delegated main.qml helper did.
compare(CostPresentation.formatCount(fmt, null), "0")
var italian = CostPresentation.numberFormat(".", ",")
compare(CostPresentation.formatCount(italian, 99.95), "100")
compare(CostPresentation.formatCount(italian, 99.94), "99,9")
compare(CostPresentation.formatCount(italian, 1234.5), "1.235")
compare(CostPresentation.formatCount(null, 12.5), "12.5")
}
// A tiny negative balance rounds to a displayed zero. The sign must not
// survive as the negative-zero string "-0".
function test_formatCountDropsTheSignWhenANegativeRoundsToZero() {
compare(CostPresentation.formatCount(fmt, -0.04), "0")
compare(CostPresentation.formatCount(fmt, -0.049), "0")
var italian = CostPresentation.numberFormat(".", ",")
compare(CostPresentation.formatCount(italian, -0.04), "0")
// A negative that survives rounding keeps its sign.
compare(CostPresentation.formatCount(fmt, -0.05), "-0.1")
compare(CostPresentation.formatCount(fmt, -0.4), "-0.4")
compare(CostPresentation.formatCount(fmt, -5), "-5")
}
function test_tokenCountStringScalesAndDropsTrailingZero() {
compare(CostPresentation.tokenCountString(999), "999")
compare(CostPresentation.tokenCountString(1000), "1K")
compare(CostPresentation.tokenCountString(1500), "1.5K")
compare(CostPresentation.tokenCountString(15000), "15K")
compare(CostPresentation.tokenCountString(2500000), "2.5M")
compare(CostPresentation.tokenCountString(3000000000), "3B")
compare(CostPresentation.tokenCountString(-1500), "-1.5K")
compare(CostPresentation.tokenCountString("abc"), "-")
}
// A value that rounds up across a unit boundary must promote to the larger
// unit instead of printing an overflowing one ("1000K", "1000M").
function test_tokenCountStringPromotesAtRoundedBoundaries() {
compare(CostPresentation.tokenCountString(999.6), "1K")
compare(CostPresentation.tokenCountString(999999), "1M")
compare(CostPresentation.tokenCountString(994999), "995K")
compare(CostPresentation.tokenCountString(999600), "1M")
compare(CostPresentation.tokenCountString(-999600), "-1M")
compare(CostPresentation.tokenCountString(999999999), "1B")
compare(CostPresentation.tokenCountString(999499999), "999M")
}
// The regression this guards: a marker or bar drawn against the wrong
// metric claims a spend level the payload never reported.
function test_sparklineMaxFollowsTheSelectedMetric() {
var points = [dailyPoint("Mon", 5, 900), dailyPoint("Tue", 2, 4000)]
compare(CostPresentation.sparklineMax(points, false), 5)
compare(CostPresentation.sparklineMax(points, true), 4000)
compare(CostPresentation.sparklineMax([], false), 0)
compare(CostPresentation.sparklineMax(null, false), 0)
}
function test_chartPointsDropUnavailableCostButKeepTokens() {
var points = [dailyPoint("Mon", null, 250)]
compare(CostPresentation.chartPoints(fmt, points, false).length, 0)
compare(CostPresentation.chartPoints(fmt, points, true)[0].value, 250)
}
function test_peakPointNamesTheDayTheBarsHighlight() {
var points = [dailyPoint("Mon", 5, 900), dailyPoint("Tue", 2, 4000)]
compare(CostPresentation.peakPoint(points, false).label, "Mon")
compare(CostPresentation.peakPoint(points, true).label, "Tue")
}
function test_peakPointIsNullWhenNothingWasSpent() {
compare(CostPresentation.peakPoint([dailyPoint("Mon", 0, 0)], false), null)
compare(CostPresentation.peakPoint([], false), null)
compare(CostPresentation.peakPoint(null, false), null)
compare(CostPresentation.peakPoint([null, "invalid", 42], false), null)
compare(CostPresentation.peakPoint([null, dailyPoint("Tue", 4, 0)], false).label, "Tue")
}
function test_peakPointLeavesAnEmptyLabelForTheCallerToWord() {
compare(CostPresentation.peakPoint([dailyPoint("", 5, 900)], false).label, "")
}
// Null entries carry no data: the peak skips them like uniqueCostDayIndex
// does, and breakdown rows never read a token count from one.
function test_peakPointAndBreakdownRowsSkipNullEntries() {
compare(CostPresentation.peakPoint([null, dailyPoint("Mon", 5, 900)], false).label, "Mon")
compare(CostPresentation.peakPoint([null, null], false), null)
compare(CostPresentation.breakdownRows([null, { label: "ok", tokens: 5 }]).length, 1)
compare(CostPresentation.breakdownRows([null]).length, 0)
}
function test_averageDailyValueDividesByEveryPlottedDay() {
var points = [dailyPoint("Mon", 3, 0), dailyPoint("Tue", 0, 0), dailyPoint("Wed", 6, 0)]
compare(CostPresentation.averageDailyValue(points, false).value, 3)
compare(CostPresentation.averageDailyValue([], false), null)
}
function test_averageDailyValueExcludesUnavailableMetricDays() {
var points = [
dailyPoint("Mon", null, 100),
dailyPoint("Tue", 6, 300)
]
compare(CostPresentation.averageDailyValue(points, false).value, 6)
compare(CostPresentation.averageDailyValue(points, true).value, 200)
}
function test_perMillionAmountNeedsBothHalvesOfTheRatio() {
compare(CostPresentation.perMillionAmount({ totals: { cost: 2, tokens: 1000000, currency: "USD" } }).value, 2)
compare(CostPresentation.perMillionAmount({ totals: { cost: 2, tokens: 0 } }), null)
compare(CostPresentation.perMillionAmount({ totals: { cost: 0, tokens: 500 } }), null)
compare(CostPresentation.perMillionAmount(null), null)
}
function test_chartBarGeometryKeepsTheLastBarInsideTheCanvas() {
var dense = CostPresentation.chartBarGeometry(100, 365)
verify(dense.offset >= 0)
verify(dense.offset + dense.step * (365 - 1) + dense.barWidth <= 100.0001)
verify(dense.barWidth >= 1)
var sparse = CostPresentation.chartBarGeometry(100, 2)
compare(sparse.offset, 2)
compare(sparse.gap, 4)
compare(sparse.step, 50)
compare(sparse.barWidth, 46)
}
function test_chartLineGeometryInsetsEndpointMarkers() {
compare(CostPresentation.chartLineX(100, 3, 0, 3.5), 3.5)
compare(CostPresentation.chartLineX(100, 3, 1, 3.5), 50)
compare(CostPresentation.chartLineX(100, 3, 2, 3.5), 96.5)
compare(CostPresentation.chartLineX(4, 2, 0, 3.5), 2)
compare(CostPresentation.chartLineX(4, 2, 1, 3.5), 2)
compare(CostPresentation.chartLineX(100, 1, 0, 3.5), 50)
}
function test_chartLineHitTestingMatchesInsetMarkerPositions() {
compare(CostPresentation.chartLineIndexAt(300, 120, 3.5, 3.5), 0)
compare(CostPresentation.chartLineIndexAt(300, 120, 296.5, 3.5), 119)
compare(CostPresentation.chartLineIndexAt(300, 120, 150, 3.5), 60)
compare(CostPresentation.chartLineIndexAt(300, 120, 0, 3.5), 0)
compare(CostPresentation.chartLineIndexAt(300, 120, 300, 3.5), 119)
}
function test_chartLineGeometryInsetsVerticalMarkers() {
compare(CostPresentation.chartLineY(100, 0, 3.5), 96.5)
compare(CostPresentation.chartLineY(100, 0.5, 3.5), 50)
compare(CostPresentation.chartLineY(100, 1, 3.5), 3.5)
compare(CostPresentation.chartLineY(4, 0, 3.5), 2)
compare(CostPresentation.chartLineY(4, 1, 3.5), 2)
compare(CostPresentation.chartLineY(100, -1, 3.5), 96.5)
compare(CostPresentation.chartLineY(100, 2, 3.5), 3.5)
}
function test_chartBarGeometrySurvivesAZeroPointChart() {
var empty = CostPresentation.chartBarGeometry(0, 0)
compare(empty.step, 0)
compare(empty.barWidth, 1)
compare(empty.offset, 0)
}
function test_chartPointsClampNegativeValuesAndBoundLabels() {
var points = CostPresentation.chartPoints(fmt, [dailyPoint("Mon", -4, 100)], false)
compare(points[0].value, 0)
compare(points[0].displayValue, "$0.00")
// `long` is a QML reserved word, so the label fixture cannot borrow it.
var oversized = CostPresentation.chartPoints(fmt, [dailyPoint(new Array(300).join("x"), 1, 1)], false)
compare(oversized[0].label.length, 120)
}
function test_sparklineSummaryReportsTheNewestPoint() {
var points = [dailyPoint("Mon", 5, 900), dailyPoint("Tue", 2, 4000)]
compare(CostPresentation.sparklineSummary(fmt, points, false).label, "Tue")
compare(CostPresentation.sparklineSummary(fmt, points, false).value, "$2.00")
compare(CostPresentation.sparklineSummary(fmt, points, true).value, "4K")
compare(CostPresentation.sparklineSummary(fmt, [], false), null)
}
function test_sparklineSummaryHidesUnavailableCostButKeepsTokens() {
var points = [dailyPoint("Mon", null, 250)]
compare(CostPresentation.sparklineSummary(fmt, points, false), null)
compare(CostPresentation.sparklineSummary(fmt, points, true).value, "250")
}
function test_breakdownRowsDropZeroAndMissingCounts() {
var rows = CostPresentation.breakdownRows([
{ label: "Total", tokens: 1500 },
{ label: "Input", tokens: 0 },
{ label: "Output", tokens: undefined },
{ label: "Cache", tokens: "abc" },
null,
"invalid",
42
])
compare(rows.length, 1)
compare(rows[0].label, "Total")
compare(rows[0].value, "1.5K")
}
function test_tokenSummaryOmitsTheHalfThatIsMissing() {
compare(CostPresentation.tokenSummary(fmt, 3, 0, "USD", ""), "$3.00")
compare(CostPresentation.tokenSummary(fmt, 0, 2000, "USD", ""), "2K")
compare(CostPresentation.tokenSummary(fmt, 0, 0, "USD", ""), "")
compare(CostPresentation.tokenSummary(fmt, 3, 2000, "USD", "2K tokens"), "$3.00 · 2K tokens")
}
function test_historyRowsRunNewestFirstAndScaleToTheSelectedMetric() {
var tokenCost = { daily: [
dailyPoint("Mon", 1, 4000),
dailyPoint("Tue", 4, 1000)
] }
var byCost = CostPresentation.historyRows(fmt, tokenCost, false, "Latest")
compare(byCost[0].label, "Tue")
compare(byCost[0].isPeak, true)
compare(byCost[1].isPeak, false)
var byTokens = CostPresentation.historyRows(fmt, tokenCost, true, "Latest")
compare(byTokens[0].label, "Tue")
compare(byTokens[0].isPeak, false)
compare(byTokens[1].isPeak, true)
}
function test_historyRowsKeepAtMostSevenDays() {
var daily = []
for (var i = 0; i < 30; i++) {
daily.push(dailyPoint("d" + i, i + 1, 0))
}
compare(CostPresentation.historyRows(fmt, { daily: daily }, false, "Latest").length, 7)
}
function test_historyRowsUseTheCallerFallbackLabel() {
var rows = CostPresentation.historyRows(fmt, { daily: [dailyPoint("", 1, 0)] }, false, "Latest")
compare(rows[0].label, "Latest")
}
function test_historyRowsHideUnavailableCostButKeepTokenHistory() {
var tokenCost = { daily: [
dailyPoint("Mon", null, 100),
dailyPoint("Tue", null, 250)
] }
compare(CostPresentation.historyRows(fmt, tokenCost, false, "Latest").length, 0)
compare(CostPresentation.historyRows(fmt, tokenCost, true, "Latest").length, 2)
}
function test_historyRowsUseTheSelectedMetricForZeroTokenGaps() {
var rows = CostPresentation.historyRows(fmt, {
daily: [dailyPoint("Mon", null, 0)]
}, true, "Latest")
compare(rows.length, 1)
compare(rows[0].value, "0")
}
function test_historyRowsKeepAVisibleBarForSmallDays() {
var rows = CostPresentation.historyRows(fmt, { daily: [
dailyPoint("Mon", 1000, 0),
dailyPoint("Tue", 1, 0)
] }, false, "Latest")
compare(rows[0].percent, 3)
}
function test_historyRowsDistinguishZeroFromSmallPositiveDays_data() {
return [
{ tag: "cost", showsTokens: false, zeroCost: 0, zeroTokens: 2000 },
{ tag: "tokens", showsTokens: true, zeroCost: 2000, zeroTokens: 0 }
]
}
function test_historyRowsDistinguishZeroFromSmallPositiveDays(data) {
var rows = CostPresentation.historyRows(fmt, { daily: [
dailyPoint("Mon", 1000, 1000),
dailyPoint("Tue", 1, 1),
dailyPoint("Wed", data.zeroCost, data.zeroTokens)
] }, data.showsTokens, "Latest")
compare(rows[0].percent, 0)
compare(rows[0].isPeak, false)
compare(rows[1].percent, 3)
compare(rows[2].percent, 100)
}
function test_historyRowsSurviveAnEmptyPayload() {
compare(CostPresentation.historyRows(fmt, null, false, "Latest").length, 0)
compare(CostPresentation.historyRows(fmt, { daily: [] }, false, "Latest").length, 0)
compare(CostPresentation.historyRows(fmt, { daily: "invalid" }, false, "Latest").length, 0)
}
function test_breakdownRowsSurviveNonArrayInputs() {
compare(CostPresentation.breakdownRows(null).length, 0)
compare(CostPresentation.breakdownRows(undefined).length, 0)
compare(CostPresentation.breakdownRows("invalid").length, 0)
}
function test_modelRowsSurviveNonArrayInputs() {
compare(CostPresentation.modelRows(fmt, null, null).length, 0)
compare(CostPresentation.modelRows(fmt, { models: "invalid" }, null).length, 0)
compare(CostPresentation.modelRows(fmt, { models: [null, "invalid", 42] }, null).length, 0)
}
function test_chartPointsAndSparklineMaxSurviveNonArrayInputs() {
compare(CostPresentation.chartPoints(fmt, null, false).length, 0)
compare(CostPresentation.chartPoints(fmt, "invalid", false).length, 0)
compare(CostPresentation.sparklineMax(null, false), 0)
compare(CostPresentation.sparklineMax("invalid", false), 0)
compare(CostPresentation.sparklineSummary(fmt, "invalid", false), null)
}
function test_averageDailyValueAndPeakPointSurviveNonArrayInputs() {
compare(CostPresentation.averageDailyValue(null, false), null)
compare(CostPresentation.averageDailyValue("invalid", false), null)
compare(CostPresentation.peakPoint(null, false), null)
compare(CostPresentation.peakPoint("invalid", false), null)
}
function test_spendHelpersSurviveNonArrayInputs() {
var arrayLike = { length: 1, 0: null }
compare(CostPresentation.spendDailyPoints(fmt, arrayLike, false).length, 0)
compare(CostPresentation.spendCurrency(arrayLike), "USD")
compare(CostPresentation.spendHasMixedCostCurrencies(arrayLike), false)
compare(CostPresentation.spendTotals("invalid"), null)
compare(CostPresentation.historyStillBuilding("invalid"), false)
}
function test_modelRowsLetTheCallerWordTheTokenHalf() {
var rows = CostPresentation.modelRows(fmt, { models: [
{ label: "gpt", cost: 1, tokens: 2000, currency: "USD" }
] }, function(tokens) { return CostPresentation.tokenCountString(tokens) + " tokens" })
compare(rows[0].value, "$1.00 · 2K tokens")
}
// A snapshot answered for a different window must not be summed into the
// range the user has since selected.
function test_snapshotMatchesRangeRejectsAStaleWindow() {
verify(CostPresentation.snapshotMatchesRange({ historyDays: 30 }, 30))
verify(!CostPresentation.snapshotMatchesRange({ historyDays: 7 }, 30))
verify(!CostPresentation.snapshotMatchesRange({ historyDays: "abc" }, 30))
verify(!CostPresentation.snapshotMatchesRange(null, 30))
}
function test_spendSnapshotsFilterByRangeAndSortByTitle() {
var tokenCosts = {
zed: { provider: "zed", historyDays: 30 },
alpha: { provider: "alpha", historyDays: 30 },
stale: { provider: "stale", historyDays: 7 }
}
var snapshots = CostPresentation.spendSnapshots(tokenCosts, 30, function(id) {
return id === "zed" ? "Zed" : "Alpha"
})
compare(snapshots.length, 2)
compare(snapshots[0].provider, "alpha")
}
function test_spendSnapshotsIgnoreInheritedKeys() {
var tokenCosts = { own: { provider: "own", historyDays: 30 } }
compare(CostPresentation.spendSnapshots(tokenCosts, 30, null).length, 1)
compare(CostPresentation.spendSnapshots({}, 30, null).length, 0)
}
function test_spendCurrencyPrefersTotalsThenFallsBackToDaily() {
compare(CostPresentation.spendCurrency([{ totals: { currency: "EUR" } }]), "EUR")
compare(CostPresentation.spendCurrency([{ totals: {}, daily: [dailyPoint("Mon", 1, 1, "GBP")] }]), "GBP")
compare(CostPresentation.spendCurrency([]), "USD")
}
function test_spendCurrencyPrefersPricedDataOverTokenOnlyFallbacks() {
var costs = [
{
totals: { cost: null, tokens: 250, currency: "USD" },
daily: [dailyPoint("Mon", null, 250, "USD")]
},
{
totals: { cost: 9, tokens: 400, currency: "EUR" },
daily: [dailyPoint("Mon", 9, 400, "EUR")]
}
]
compare(CostPresentation.spendCurrency(costs), "EUR")
var totals = CostPresentation.spendTotals(costs)
compare(totals.cost, 9)
compare(totals.tokens, 650)
compare(totals.currency, "EUR")
var costPoints = CostPresentation.spendDailyPoints(fmt, costs, false)
compare(costPoints.length, 1)
compare(costPoints[0].value, 9)
var tokenPoints = CostPresentation.spendDailyPoints(fmt, costs, true)
compare(tokenPoints[0].value, 650)
}
// Money in mixed currencies cannot be summed, but token counts are
// currency-free: filtering them would drop whole providers from the chart.
function test_spendDailyPointsDropForeignMoneyButKeepForeignTokens() {
var costs = [
{ totals: { currency: "USD" }, daily: [dailyPoint("Mon", 2, 100, "USD")] },
{ totals: { currency: "EUR" }, daily: [dailyPoint("Mon", 9, 400, "EUR")] }
]
var byCost = CostPresentation.spendDailyPoints(fmt, costs, false)
compare(byCost.length, 1)
compare(byCost[0].value, 2)
var byTokens = CostPresentation.spendDailyPoints(fmt, costs, true)
compare(byTokens[0].value, 500)
}
function test_spendDailyPointsDropUnavailableCostButKeepTokens() {
var costs = [{
totals: { cost: null, tokens: 250, currency: "USD" },
daily: [dailyPoint("Mon", null, 250, "USD")]
}]
compare(CostPresentation.spendDailyPoints(fmt, costs, false).length, 0)
compare(CostPresentation.spendDailyPoints(fmt, costs, true)[0].value, 250)
}
function test_spendDailyPointsRejectPrototypePollutingLabels() {
var costs = [{ totals: { currency: "USD" }, daily: [
dailyPoint("__proto__", 5, 5, "USD"),
dailyPoint("constructor", 5, 5, "USD"),
dailyPoint("", 5, 5, "USD"),
dailyPoint("Mon", 5, 5, "USD")
] }]
var points = CostPresentation.spendDailyPoints(fmt, costs, false)
compare(points.length, 1)
compare(points[0].label, "Mon")
}
function test_spendDailyPointsSortByLabelAndCarryDisplayText() {
var costs = [{ totals: { currency: "USD" }, daily: [
dailyPoint("2026-08-02", 1, 0, "USD"),
dailyPoint("2026-08-01", 2, 0, "USD")
] }]
var points = CostPresentation.spendDailyPoints(fmt, costs, false)
compare(points[0].label, "2026-08-01")
compare(points[0].displayValue, "$2.00")
}
function test_spendHeatmapCellsPadTheOldestCornerAndKeepTheNewestDayLast() {
var points = []
for (var day = 0; day < 30; day++) {
points.push({ label: "day-" + day, value: day, displayValue: "" })
}
var cells = CostPresentation.spendHeatmapCells(points, 35)
compare(cells.length, 35)
for (var padded = 0; padded < 5; padded++) {
compare(cells[padded], null)
}
compare(cells[5].label, "day-0")
compare(cells[34].label, "day-29")
}
function test_spendHeatmapCellsDropTheOldestDaysBeyondCapacity() {
var cells = CostPresentation.spendHeatmapCells([
{ label: "a" }, { label: "b" }, { label: "c" }
], 2)
compare(cells.length, 2)
compare(cells[0].label, "b")
compare(cells[1].label, "c")
}
function test_spendHeatmapCellsSurviveMissingAndNonsenseInput() {
compare(CostPresentation.spendHeatmapCells(undefined, 7).length, 7)
compare(CostPresentation.spendHeatmapCells("not an array", 2)[0], null)
compare(CostPresentation.spendHeatmapCells([{ label: "a" }], 0).length, 0)
compare(CostPresentation.spendHeatmapCells([{ label: "a" }], -4).length, 0)
compare(CostPresentation.spendHeatmapCells([{ label: "a" }], NaN).length, 0)
compare(CostPresentation.spendHeatmapCells([{ label: "a" }], 2.7).length, 2)
}
function test_spendTotalsKeepAllCurrencyFreeTokens() {
var totals = CostPresentation.spendTotals([
{ totals: { cost: 2, tokens: 100, currency: "USD" } },
{ totals: { cost: 9, tokens: 400, currency: "EUR" } }
])
compare(totals.cost, 2)
compare(totals.tokens, 500)
compare(totals.currency, "USD")
verify(totals.hasMixedCostCurrencies)
}
function test_spendCurrencyStatusIgnoresTokenOnlyProviders() {
var totals = CostPresentation.spendTotals([
{ totals: { cost: null, tokens: 100, currency: "USD" } },
{ totals: { cost: 9, tokens: 400, currency: "EUR" } }
])
compare(totals.currency, "EUR")
verify(!totals.hasMixedCostCurrencies)
}
function test_spendCurrencyStatusChecksDailyCostWhenTotalsAreUnavailable() {
verify(CostPresentation.spendHasMixedCostCurrencies([
{
totals: { cost: 2, tokens: 100, currency: "USD" },
daily: [dailyPoint("Mon", 2, 100, "USD")]
},
{
totals: { cost: null, tokens: 400, currency: "EUR" },
daily: [dailyPoint("Mon", 9, 400, "EUR")]
}
]))
}
function test_spendTotalsPreserveUnavailableCostAndKeepTokens() {
var totals = CostPresentation.spendTotals([
{ totals: { cost: null, tokens: 250, currency: "USD" } }
])
compare(totals.cost, null)
compare(totals.tokens, 250)
compare(totals.currency, "USD")
}
function test_spendTotalsKeepUnknownTokensWithoutDroppingCost() {
var costs = [{ totals: { cost: 3, tokens: null, currency: "USD" } }]
compare(CostPresentation.spendTotals(costs).tokens, null)
compare(CostPresentation.spendTotals(costs).cost, 3)
costs.push({ totals: { cost: 2, tokens: 0, currency: "USD" } })
compare(CostPresentation.spendTotals(costs).tokens, 0)
compare(CostPresentation.spendTotals(costs).cost, 5)
costs[0].totals.tokens = 1e308
costs[1].totals.tokens = 1e308
compare(CostPresentation.spendTotals(costs).tokens, null)
}
function test_spendTotalsAreNullWithNoSnapshots() {
compare(CostPresentation.spendTotals([]), null)
compare(CostPresentation.spendTotals(null), null)
}
function test_costTrustSummaryIsQuietForLegacyAndExactUnspecifiedData() {
compare(CostPresentation.costTrustSummary([]), null)
compare(CostPresentation.costTrustSummary(null), null)
compare(CostPresentation.costTrustSummary([{ totals: { currency: "USD" } }]), null)
compare(CostPresentation.costTrustSummary([trustedCost("USD", {
priced: 3, unpriced: 0, unmetered: 0, estimated: 0
}, "")]), null)
compare(CostPresentation.costTrustSummary([{
totals: { currency: "USD" },
trust: { coverage: { priced: "3" }, sourceKind: "not-a-semantic-value" }
}]), null)
function InheritedTrust() {}
InheritedTrust.prototype.coverage = {
priced: 0, unpriced: 1, unmetered: 0, estimated: 0
}
InheritedTrust.prototype.sourceKind = "unknown"
compare(CostPresentation.costTrustSummary([{
totals: { currency: "USD" },
trust: new InheritedTrust()
}]), null)
}
function test_costTrustSummaryIgnoresTokenOnlySnapshots() {
compare(CostPresentation.costTrustSummary([{
totals: { cost: null, tokens: 250, currency: "USD" },
trust: { coverage: null, sourceKind: "unknown" }
}]), null)
}
function test_costTrustSummaryIgnoresEmptySnapshots_data() {
return [
{ tag: "missing history flag" },
{ tag: "established history", historyEstablished: true },
{ tag: "unestablished history", historyEstablished: false }
]
}
function test_costTrustSummaryIgnoresEmptySnapshots(data) {
var emptySnapshot = {
totals: { cost: null, tokens: 0, currency: "USD" },
daily: [],
trust: {
coverage: {
priced: 0, unpriced: 0, unmetered: 0, estimated: 0
},
sourceKind: "unknown"
}
}
if (data.historyEstablished !== undefined) {
emptySnapshot.historyCoverageEstablished = data.historyEstablished
}
var summary = CostPresentation.costTrustSummary([
trustedCost("USD", {
priced: 1, unpriced: 0, unmetered: 0, estimated: 1
}, "listPrice"),
emptySnapshot
])
compare(summary.sourceKind, "listPrice")
compare(summary.valueMode, "estimated")
}
function test_costTrustSummaryKeepsTokenOnlyGapsInAMixedTotal() {
var summary = CostPresentation.costTrustSummary([
trustedCost("USD", null, "vendor"),
{
totals: { cost: null, tokens: 250, currency: "USD" },
historyCoverageEstablished: false,
trust: { coverage: null, sourceKind: "unknown" }
}
])
compare(summary.level, "warning")
compare(summary.valueMode, "approximate")
compare(summary.sourceKind, "unknown")
}
function test_costTrustSummaryKeepsCurrencyFreeTokenOnlyGaps() {
var summary = CostPresentation.costTrustSummary([
{
totals: { cost: null, tokens: 250, currency: "USD" },
trust: { coverage: null, sourceKind: "unknown" }
},
trustedCost("EUR", null, "vendor")
])
compare(summary.level, "warning")
compare(summary.valueMode, "approximate")
compare(summary.sourceKind, "unknown")
}
function test_costTrustSummaryMapsEstimateAndSourceToSemanticKeys() {
var summary = CostPresentation.costTrustSummary([trustedCost("USD", {
priced: 4, unpriced: 0, unmetered: 0, estimated: 1
}, "listPrice")])
compare(summary.level, "information")
compare(summary.valueMode, "estimated")
compare(summary.sourceKind, "listPrice")
verify(summary.hasEstimated)
verify(!summary.hasUnpriced)
verify(!summary.hasUnmetered)
}
function test_costTrustSummaryMakesIncompleteCoverageAWarning() {
var summary = CostPresentation.costTrustSummary([trustedCost("USD", {
priced: 5, unpriced: 2, unmetered: 1, estimated: 0
}, "vendor")])
compare(summary.level, "warning")
compare(summary.valueMode, "partial")
compare(summary.sourceKind, "vendor")
verify(summary.hasUnpriced)
verify(summary.hasUnmetered)
}
function test_costTrustSummaryTreatsUnknownAsApproximateAndConservative() {
var summary = CostPresentation.costTrustSummary([
trustedCost("USD", null, "listPrice"),
trustedCost("USD", null, "unknown")
])
compare(summary.level, "warning")
compare(summary.valueMode, "approximate")
compare(summary.sourceKind, "unknown")
}
function test_costTrustSummaryDoesNotClassifyLegacyCostFromTrustedSubset() {
var summary = CostPresentation.costTrustSummary([
trustedCost("USD", null, "vendor"),
{ totals: { cost: 9, tokens: 90, currency: "USD" }, trust: null }
])
compare(summary.level, "warning")
compare(summary.valueMode, "approximate")
compare(summary.sourceKind, "unknown")
}
function test_costTrustSummaryFoldsKnownSourcesWithoutCallingMixedIncomplete() {
var summary = CostPresentation.costTrustSummary([
trustedCost("USD", null, "listPrice"),
trustedCost("USD", null, "vendor")
])
compare(summary.level, "information")
compare(summary.valueMode, "estimated")
compare(summary.sourceKind, "mixed")
verify(summary.hasEstimated)
verify(!summary.hasUnpriced)
verify(!summary.hasUnmetered)
}
function test_costTrustSummaryUsesTheSpendTotalCurrencyEligibility() {
var summary = CostPresentation.costTrustSummary([
trustedCost("USD", null, "listPrice"),
trustedCost("EUR", {
priced: 0, unpriced: 3, unmetered: 0, estimated: 0
}, "unknown")
])
compare(summary.level, "information")
compare(summary.valueMode, "estimated")
compare(summary.sourceKind, "listPrice")
verify(!summary.hasUnpriced)
}
function test_costTrustSummaryDoesNotConfuseScanCoverageWithPricingCoverage() {
compare(CostPresentation.costTrustSummary([{
totals: { currency: "USD" },
historyCoverageEstablished: false
}]), null)
}
function test_costTrustNoticeDismissalSurvivesRefreshUntilMeaningChanges() {
var estimated = CostPresentation.costTrustSummary([trustedCost("USD", {
priced: 4, unpriced: 0, unmetered: 0, estimated: 1
}, "listPrice")])
var initial = CostPresentation.costTrustNoticeTransition(
estimated, null, false)
verify(initial.shouldShow)
var dismissed = CostPresentation.costTrustNoticeTransition(
estimated, initial, true)
verify(!dismissed.shouldShow)
var refreshed = CostPresentation.costTrustNoticeTransition(
CostPresentation.costTrustSummary([trustedCost("USD", {
priced: 4, unpriced: 0, unmetered: 0, estimated: 1
}, "listPrice")]),
dismissed,
false)
verify(!refreshed.shouldShow)
var partial = CostPresentation.costTrustSummary([trustedCost("USD", {
priced: 4, unpriced: 1, unmetered: 0, estimated: 1
}, "listPrice")])
var changed = CostPresentation.costTrustNoticeTransition(
partial, refreshed, false)
verify(changed.shouldShow)
verify(changed.key !== dismissed.key)
var dismissedPartial = CostPresentation.costTrustNoticeTransition(
partial, changed, true)
var returned = CostPresentation.costTrustNoticeTransition(
estimated, dismissedPartial, false)
verify(returned.shouldShow)
}
function test_costTrustNoticeDismissalSurvivesNoticeRecreationPerScope() {
var summary = CostPresentation.costTrustSummary([trustedCost("USD", {
priced: 4, unpriced: 1, unmetered: 0, estimated: 1
}, "listPrice")])
var initial = CostPresentation.costTrustNoticeStoreTransition(
summary, ({}), "provider:codex", false)
verify(initial.state.shouldShow)
var dismissed = CostPresentation.costTrustNoticeStoreTransition(
summary, initial.states, "provider:codex", true)
verify(!dismissed.state.shouldShow)
verify(dismissed.states !== initial.states)
verify(!initial.states["provider:codex"].dismissed)
var temporarilyMissing = CostPresentation.costTrustNoticeStoreTransition(
null, dismissed.states, "provider:codex", false)
verify(!temporarilyMissing.state.shouldShow)
// A new CostTrustNotice instance must recover the dismissal from its
// persistent owner even if its summary binding was briefly empty.
var recreated = CostPresentation.costTrustNoticeStoreTransition(
summary, temporarilyMissing.states, "provider:codex", false)
verify(!recreated.state.shouldShow)
// Provider details and aggregate Spend are separate information scopes.
var aggregate = CostPresentation.costTrustNoticeStoreTransition(
summary, dismissed.states, "spend", false)
verify(aggregate.state.shouldShow)
}
function test_costTrustNoticeStoreBoundsAndRejectsUnsafeScopes() {
var summary = CostPresentation.costTrustSummary([trustedCost("USD", {
priced: 4, unpriced: 1, unmetered: 0, estimated: 1
}, "listPrice")])
var oversized = ({})
for (var i = 0; i < 200; i++) {
oversized["provider:" + i] = { key: "old", dismissed: true }
}
var bounded = CostPresentation.costTrustNoticeStoreTransition(
summary, oversized, "spend", false)
verify(Object.keys(bounded.states).length <= 128)
verify(Object.prototype.hasOwnProperty.call(bounded.states, "spend"))
var unsafe = CostPresentation.costTrustNoticeStoreTransition(
summary, bounded.states, "__proto__", true)
verify(!Object.prototype.hasOwnProperty.call(unsafe.states, "__proto__"))
verify(unsafe.state.dismissed)
}
function test_costTrustNoticeTransitionRejectsMalformedSummaries() {
var invalidSummaries = [null, undefined, [], "estimated", 7, ({})]
for (var i = 0; i < invalidSummaries.length; i++) {
var state = CostPresentation.costTrustNoticeTransition(
invalidSummaries[i],
{ key: "old", dismissed: true, shouldShow: false },
true)
compare(state.key, "")
verify(!state.dismissed)
verify(!state.shouldShow)
}
}
function test_costTrustNoticeTransitionIgnoresInheritedLevel() {
function InheritedWarning() {}
InheritedWarning.prototype.level = "warning"
var summary = new InheritedWarning()
summary.sourceKind = "listPrice"
summary.hasEstimated = true
summary.hasUnpriced = false
summary.hasUnmetered = false
var state = CostPresentation.costTrustNoticeTransition(
summary, null, false)
compare(state.key, "information|listPrice|estimated|priced|metered")
verify(state.shouldShow)
}
function test_costTrustNoticeTransitionRejectsMalformedPreviousState() {
var summary = CostPresentation.costTrustSummary([trustedCost("USD", {
priced: 4, unpriced: 0, unmetered: 0, estimated: 1
}, "listPrice")])
function InheritedDismissal() {}
InheritedDismissal.prototype.key = "inherited"
InheritedDismissal.prototype.dismissed = true
var invalidStates = [
null,
undefined,
[],
"dismissed",
{ key: 7, dismissed: "yes" },
new InheritedDismissal()
]
for (var i = 0; i < invalidStates.length; i++) {
var state = CostPresentation.costTrustNoticeTransition(
summary, invalidStates[i], false)
verify(state.key.length > 0)
verify(state.key.length < 80)
verify(!state.dismissed)
verify(state.shouldShow)
}
}
// A missing flag counts as established, so older CLI payloads do not print
// a permanent "still collecting" note.
function test_historyStillBuildingOnlyOnAnExplicitFalse() {
verify(CostPresentation.historyStillBuilding([{ historyCoverageEstablished: false }]))
verify(!CostPresentation.historyStillBuilding([{ historyCoverageEstablished: true }]))
verify(!CostPresentation.historyStillBuilding([{}]))
verify(!CostPresentation.historyStillBuilding([]))
verify(!CostPresentation.historyStillBuilding([null, "stale", 42]))
}
function test_malformedSnapshotsDegradeInsteadOfThrowing() {
var points = CostPresentation.spendDailyPoints(fmt, [
null,
{ daily: null, totals: {} },
{ daily: { length: 1000000000000 }, totals: {} },
{ daily: [null, 42, "Mon", { label: "Mon", cost: 2, tokens: 10, currency: "USD" }], totals: {} }
], false)
compare(points.length, 1)
compare(points[0].label, "Mon")
var rows = CostPresentation.projectRows([
null,
{ provider: "codex", projects: null },
{ provider: "codex", projects: { rows: [0, 1, null, { label: "Kept", cost: 3, tokens: 30, currency: "USD" }] } }
], false)
compare(rows.rows.length, 1)
compare(rows.rows[0].label, "Kept")
verify(!rows.truncated)
var totals = CostPresentation.spendTotals([{ totals: { tokens: "100", currency: "USD" } }])
compare(totals.tokens, null)
compare(CostPresentation.spendTotals([null, { totals: { cost: 2, tokens: 40, currency: "USD" } }]).tokens, 40)
verify(!CostPresentation.historyStillBuilding([null]))
compare(CostPresentation.spendCurrency([null]), "USD")
}
}