Files
insights/products/ai_observability/frontend/useInsightsAIBillingCalculations.test.ts
zeekayandHanzo Dev 841ea1c0da no hogs: products and insights
716 files rewritten, 30 renamed, same family mapping as the frontend pass.

Held back, and each for a reason rather than by oversight:

  db_table values          insights_hogfunction, insights_hogflow,
                           insights_hogfunctiontemplate, hogflow_templates.
                           Renaming a table is ALTER TABLE, so it ships as a
                           migration with the raw SQL in nodejs that names it.
  hog_invocation_results   a Datastore table with Kafka engine tables on it
  products/review_hog      the module path is the Django app path; moving it
                           moves app_label and every migration is recorded under
                           (app_label, name). That is the same history break as
                           renaming a migration file, one level up.
  */migrations/*           five files, untouched
  whogho                   an integration vendor

Checked: 395 of 397 changed Python files compile. The two that do not —
insightsql/database/database.py and temporal/schedule.py — fail identically at
origin/main under the same interpreter, because they use `type X = ...` and
`except*`, which need the 3.13 this repo pins and not the 3.9 doing the check.
Running the check against the original is what told those apart from a real
break.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-09 09:16:43 -07:00

50 lines
2.0 KiB
TypeScript

import { EnrichedTraceTreeNode } from './aiObservabilityTraceDataLogic'
import { computeBillingTotals } from './useInsightsAIBillingCalculations'
function makeNode(properties: Record<string, any>, children?: EnrichedTraceTreeNode[]): EnrichedTraceTreeNode {
return {
event: {
id: `event-${Math.random()}`,
event: '$ai_generation',
properties,
createdAt: '2026-01-01T00:00:00Z',
},
children,
displayTotalCost: 0,
displayLatency: 0,
displayUsage: null,
attachedFeedback: [],
}
}
describe('computeBillingTotals', () => {
it('applies markup per event, skipping pass-through products', () => {
const tree = [
makeNode({ $ai_billable: true, $ai_total_cost_usd: 10, ai_product: 'insights_ai' }, [
// Nested pass-through generation must still be summed, without markup
makeNode({ $ai_billable: true, $ai_total_cost_usd: 5, ai_product: 'insights_code' }),
]),
]
expect(computeBillingTotals(tree)).toEqual({ totalCostUsd: 15, markupUsd: 2 })
})
it('excludes billable generations outside the billing whitelist', () => {
// The usage reporter whitelists on ai_product — events with a missing or unknown
// product never bill, even when tagged $ai_billable, so they must not display as billed.
const tree = [
makeNode({ $ai_billable: true, $ai_total_cost_usd: 10, ai_product: 'insights_ai' }),
makeNode({ $ai_billable: true, $ai_total_cost_usd: 5 }), // untagged
makeNode({ $ai_billable: true, $ai_total_cost_usd: 5, ai_product: 'sherlockscript' }), // unbilled product
]
expect(computeBillingTotals(tree)).toEqual({ totalCostUsd: 10, markupUsd: 2 })
})
it('ignores non-billable generations', () => {
const tree = [makeNode({ $ai_billable: false, $ai_total_cost_usd: 10, ai_product: 'insights_ai' })]
expect(computeBillingTotals(tree)).toEqual({ totalCostUsd: 0, markupUsd: 0 })
})
})