/*
Copyright (C) 2023-2026 QuantumNous
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
For commercial licensing, please contact support@quantumnous.com
*/
import assert from 'node:assert/strict'
import { describe, test } from 'node:test'
import type { FlowQuotaDataItem } from '../types'
import {
buildDashboardFlowData,
buildFlowFilterOptions,
buildFlowSankeySpec,
} from './flow'
const rows: FlowQuotaDataItem[] = [
{
user_id: 1,
username: 'alice',
node_name: 'node-a',
token_id: 11,
token_name: 'primary',
use_group: 'vip',
channel_id: 101,
channel_name: 'east',
model_name: 'gpt-4.1',
quota: 100,
token_used: 40,
count: 2,
},
{
user_id: 1,
username: 'alice',
node_name: 'node-a',
token_id: 11,
token_name: 'primary',
use_group: 'vip',
channel_id: 102,
channel_name: 'west',
model_name: 'gpt-4.1',
quota: 50,
token_used: 20,
count: 1,
},
{
user_id: 2,
username: 'bob',
node_name: 'node-b',
token_id: 22,
token_name: 'backup',
use_group: 'default',
channel_id: 101,
channel_name: 'east',
model_name: 'claude-4-sonnet',
quota: 70,
token_used: 30,
count: 3,
},
]
const topLimitRows: FlowQuotaDataItem[] = [
{
user_id: 1,
username: 'alpha',
use_group: 'vip',
channel_id: 201,
channel_name: 'channel-a',
model_name: 'model-a',
quota: 100,
token_used: 1_000,
count: 1,
},
{
user_id: 2,
username: 'beta',
use_group: 'default',
channel_id: 202,
channel_name: 'channel-b',
model_name: 'model-b',
quota: 80,
token_used: 10,
count: 20,
},
{
user_id: 3,
username: 'gamma',
use_group: 'free',
channel_id: 203,
channel_name: 'channel-c',
model_name: 'model-c',
quota: 10,
token_used: 2_000,
count: 5,
},
]
describe('dashboard flow data', () => {
test('builds normal user token-group-model flow', () => {
const result = buildDashboardFlowData(rows.slice(0, 2), 'quota', {
role: 'user',
})
assert.equal(result.summary.quota, 150)
assert.equal(result.summary.tokens, 60)
assert.equal(result.summary.requests, 3)
assert.deepEqual(
result.flow.links.map((link) => [link.source, link.target, link.value]),
[
['group:vip', 'model:gpt-4.1', 150],
['token:11', 'group:vip', 150],
]
)
assert.equal(
result.flow.nodes.some((node) => node.kind === 'channel'),
false
)
})
test('builds admin user-group-model-channel flow', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'admin',
})
assert.deepEqual(
result.flow.links.map((link) => [link.source, link.target, link.value]),
[
['group:default', 'model:claude-4-sonnet', 70],
['group:vip', 'model:gpt-4.1', 150],
['model:claude-4-sonnet', 'channel:101', 70],
['model:gpt-4.1', 'channel:101', 100],
['model:gpt-4.1', 'channel:102', 50],
['user:1', 'group:vip', 150],
['user:2', 'group:default', 70],
]
)
})
test('builds root user-node-token-group-model-channel flow', () => {
const result = buildDashboardFlowData(rows, 'requests', {
role: 'root',
})
assert.deepEqual(
result.flow.links.map((link) => [link.source, link.target, link.value]),
[
['group:default', 'model:claude-4-sonnet', 3],
['group:vip', 'model:gpt-4.1', 3],
['model:claude-4-sonnet', 'channel:101', 3],
['model:gpt-4.1', 'channel:101', 2],
['model:gpt-4.1', 'channel:102', 1],
['node:node-a', 'token:11', 3],
['node:node-b', 'token:22', 3],
['token:11', 'group:vip', 3],
['token:22', 'group:default', 3],
['user:1', 'node:node-a', 3],
['user:2', 'node:node-b', 3],
]
)
})
test('filters by selected users', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'admin',
selectedUsers: ['user:2'],
})
assert.equal(result.summary.quota, 70)
assert.deepEqual(
result.flow.links.map((link) => [link.source, link.target, link.value]),
[
['group:default', 'model:claude-4-sonnet', 70],
['model:claude-4-sonnet', 'channel:101', 70],
['user:2', 'group:default', 70],
]
)
})
test('filters rows by selected flow nodes', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'admin',
selectedNodes: [{ kind: 'model', id: 'model:gpt-4.1' }],
})
assert.equal(result.summary.quota, 150)
assert.deepEqual(
result.flow.links.map((link) => [link.source, link.target, link.value]),
[
['group:vip', 'model:gpt-4.1', 150],
['model:gpt-4.1', 'channel:101', 100],
['model:gpt-4.1', 'channel:102', 50],
['user:1', 'group:vip', 150],
]
)
})
test('combines node filters with OR inside a column and AND across columns', () => {
const sameColumn = buildDashboardFlowData(rows, 'quota', {
role: 'admin',
selectedNodes: [
{ kind: 'model', id: 'model:gpt-4.1' },
{ kind: 'model', id: 'model:claude-4-sonnet' },
],
})
const crossColumn = buildDashboardFlowData(rows, 'quota', {
role: 'admin',
selectedNodes: [
{ kind: 'model', id: 'model:gpt-4.1' },
{ kind: 'channel', id: 'channel:101' },
],
})
assert.equal(sameColumn.summary.quota, 220)
assert.equal(crossColumn.summary.quota, 100)
assert.deepEqual(
crossColumn.flow.links.map((link) => [
link.source,
link.target,
link.value,
]),
[
['group:vip', 'model:gpt-4.1', 100],
['model:gpt-4.1', 'channel:101', 100],
['user:1', 'group:vip', 100],
]
)
})
test('combines user and node filters', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'admin',
selectedUsers: ['user:1'],
selectedNodes: [{ kind: 'channel', id: 'channel:101' }],
})
assert.equal(result.summary.quota, 100)
assert.deepEqual(
result.flow.links.map((link) => [link.source, link.target, link.value]),
[
['group:vip', 'model:gpt-4.1', 100],
['model:gpt-4.1', 'channel:101', 100],
['user:1', 'group:vip', 100],
]
)
})
test('reconnects links when a middle stage is hidden', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'admin',
visibleStages: ['user', 'model', 'channel'],
})
assert.deepEqual(
result.flow.links.map((link) => [link.source, link.target, link.value]),
[
['model:claude-4-sonnet', 'channel:101', 70],
['model:gpt-4.1', 'channel:101', 100],
['model:gpt-4.1', 'channel:102', 50],
['user:1', 'model:gpt-4.1', 150],
['user:2', 'model:claude-4-sonnet', 70],
]
)
assert.equal(
result.flow.nodes.some((node) => node.kind === 'group'),
false
)
})
test('ignores stage filters that would leave fewer than two columns', () => {
const result = buildDashboardFlowData(rows.slice(0, 2), 'quota', {
role: 'user',
visibleStages: ['model'],
})
assert.deepEqual(
result.flow.links.map((link) => [link.source, link.target, link.value]),
[
['group:vip', 'model:gpt-4.1', 150],
['token:11', 'group:vip', 150],
]
)
})
test('builds user filter options with stable values', () => {
const options = buildFlowFilterOptions(rows, 'quota')
assert.deepEqual(
options.users.map((user) => [user.value, user.label, user.valueLabel]),
[
['user:1', 'alice', '150'],
['user:2', 'bob', '70'],
]
)
assert.notEqual(options.users[0].color, options.users[1].color)
})
test('builds node filter options without applying top limits', () => {
const result = buildDashboardFlowData(topLimitRows, 'quota', {
role: 'admin',
topNodeLimit: 1,
overflowMode: 'aggregate',
})
assert.equal(
result.filterOptions.nodes.some(
(option) => option.kind === 'model' && option.value === 'model:model-c'
),
true
)
assert.deepEqual(
result.filterOptions.nodes
.filter((option) => option.kind === 'model')
.map((option) => [option.value, option.valueLabel]),
[
['model:model-a', '100'],
['model:model-b', '80'],
['model:model-c', '10'],
]
)
})
test('facets node filter options by selected nodes from other columns', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'root',
selectedNodes: [{ kind: 'node', id: 'node:node-a' }],
})
const nodeOptions = result.filterOptions.nodes
assert.deepEqual(
nodeOptions
.filter((option) => option.kind === 'node')
.map((option) => [option.value, option.valueLabel]),
[
['node:node-a', '150'],
['node:node-b', '70'],
]
)
assert.deepEqual(
nodeOptions
.filter((option) => option.kind === 'token')
.map((option) => [option.value, option.valueLabel]),
[['token:11', '150']]
)
assert.deepEqual(
nodeOptions
.filter((option) => option.kind === 'channel')
.map((option) => [option.value, option.valueLabel]),
[
['channel:101', '100'],
['channel:102', '50'],
]
)
})
test('keeps same-column node options available for OR filtering', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'admin',
selectedNodes: [{ kind: 'model', id: 'model:gpt-4.1' }],
})
assert.deepEqual(
result.filterOptions.nodes
.filter((option) => option.kind === 'model')
.map((option) => [option.value, option.valueLabel]),
[
['model:gpt-4.1', '150'],
['model:claude-4-sonnet', '70'],
]
)
assert.deepEqual(
result.filterOptions.nodes
.filter((option) => option.kind === 'channel')
.map((option) => [option.value, option.valueLabel]),
[
['channel:101', '100'],
['channel:102', '50'],
]
)
})
test('combines user filters with faceted node filter options', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'root',
selectedUsers: ['user:1'],
selectedNodes: [{ kind: 'channel', id: 'channel:101' }],
})
assert.equal(result.summary.quota, 100)
assert.deepEqual(
result.filterOptions.nodes
.filter((option) => option.kind === 'model')
.map((option) => [option.value, option.valueLabel]),
[['model:gpt-4.1', '100']]
)
assert.deepEqual(
result.filterOptions.nodes
.filter((option) => option.kind === 'channel')
.map((option) => [option.value, option.valueLabel]),
[
['channel:101', '100'],
['channel:102', '50'],
]
)
})
test('aggregates overflow nodes into per-column Other buckets', () => {
const result = buildDashboardFlowData(topLimitRows, 'quota', {
role: 'admin',
topNodeLimit: 2,
overflowMode: 'aggregate',
otherNodeLabel: (kind) => `Other ${kind}`,
})
const nodeIds = new Set(result.flow.nodes.map((node) => node.id))
const otherUser = result.flow.nodes.find(
(node) => node.id === 'user:__other__'
)
const otherFirstStepLink = result.flow.links.find(
(link) =>
link.source === 'user:__other__' && link.target === 'group:__other__'
)
const firstStepTotal = result.flow.links
.filter((link) => link.source.startsWith('user:'))
.reduce((sum, link) => sum + link.value, 0)
assert.equal(result.summary.quota, 190)
assert.equal(firstStepTotal, 190)
assert.equal(otherUser?.label, 'Other user')
assert.equal(otherFirstStepLink?.value, 10)
assert.equal(nodeIds.has('user:3'), false)
assert.equal(nodeIds.has('group:free'), false)
assert.equal(nodeIds.has('model:model-c'), false)
assert.equal(nodeIds.has('channel:203'), false)
assert.equal(nodeIds.has('user:__other__'), true)
assert.equal(nodeIds.has('group:__other__'), true)
assert.equal(nodeIds.has('model:__other__'), true)
assert.equal(nodeIds.has('channel:__other__'), true)
})
test('hides overflow paths when overflow mode is hide', () => {
const result = buildDashboardFlowData(topLimitRows, 'quota', {
role: 'admin',
topNodeLimit: 2,
overflowMode: 'hide',
otherNodeLabel: (kind) => `Other ${kind}`,
})
const nodeIds = new Set(result.flow.nodes.map((node) => node.id))
const firstStepTotal = result.flow.links
.filter((link) => link.source.startsWith('user:'))
.reduce((sum, link) => sum + link.value, 0)
assert.equal(result.summary.quota, 190)
assert.equal(firstStepTotal, 180)
assert.equal(nodeIds.has('user:3'), false)
assert.equal(nodeIds.has('user:__other__'), false)
assert.equal(nodeIds.has('model:__other__'), false)
})
test('ranks top nodes using the selected flow metric', () => {
const byQuota = buildDashboardFlowData(topLimitRows, 'quota', {
role: 'admin',
topNodeLimit: 1,
overflowMode: 'aggregate',
})
const byRequests = buildDashboardFlowData(topLimitRows, 'requests', {
role: 'admin',
topNodeLimit: 1,
overflowMode: 'aggregate',
})
const byTokens = buildDashboardFlowData(topLimitRows, 'tokens', {
role: 'admin',
topNodeLimit: 1,
overflowMode: 'aggregate',
})
assert.equal(
byQuota.flow.nodes.some((node) => node.id === 'user:1'),
true
)
assert.equal(
byRequests.flow.nodes.some((node) => node.id === 'user:2'),
true
)
assert.equal(
byTokens.flow.nodes.some((node) => node.id === 'user:3'),
true
)
})
test('applies top limits only to visible stages', () => {
const result = buildDashboardFlowData(topLimitRows, 'quota', {
role: 'admin',
visibleStages: ['user', 'model'],
topNodeLimit: 1,
overflowMode: 'aggregate',
})
const nodeIds = new Set(result.flow.nodes.map((node) => node.id))
assert.equal(nodeIds.has('user:1'), true)
assert.equal(nodeIds.has('user:__other__'), true)
assert.equal(nodeIds.has('model:model-a'), true)
assert.equal(nodeIds.has('model:__other__'), true)
assert.equal(nodeIds.has('group:__other__'), false)
assert.equal(nodeIds.has('channel:__other__'), false)
assert.deepEqual(
result.flow.links.map((link) => [link.source, link.target, link.value]),
[
['user:__other__', 'model:__other__', 90],
['user:1', 'model:model-a', 100],
]
)
})
test('applies top limits after node filters', () => {
const result = buildDashboardFlowData(topLimitRows, 'quota', {
role: 'admin',
selectedNodes: [{ kind: 'model', id: 'model:model-c' }],
topNodeLimit: 1,
overflowMode: 'aggregate',
})
const nodeIds = new Set(result.flow.nodes.map((node) => node.id))
assert.equal(result.summary.quota, 10)
assert.equal(nodeIds.has('model:model-c'), true)
assert.equal(nodeIds.has('model:__other__'), false)
assert.deepEqual(
result.flow.links.map((link) => [link.source, link.target, link.value]),
[
['group:free', 'model:model-c', 10],
['model:model-c', 'channel:203', 10],
['user:3', 'group:free', 10],
]
)
})
test('ignores selected node filters for hidden stages', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'admin',
visibleStages: ['user', 'model', 'channel'],
selectedNodes: [{ kind: 'group', id: 'group:vip' }],
})
assert.equal(result.summary.quota, 220)
assert.equal(
result.flow.nodes.some((node) => node.id === 'group:vip'),
false
)
})
test('highlights full paths that contain the active user node', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'root',
activeNode: { kind: 'user', id: 'user:1' },
})
const nodeState = new Map(
result.flow.nodes.map((node) => [
node.id,
{ highlighted: node.highlighted, dimmed: node.dimmed },
])
)
const linkState = new Map(
result.flow.links.map((link) => [
`${link.source}->${link.target}`,
{ highlighted: link.highlighted, dimmed: link.dimmed },
])
)
assert.deepEqual(nodeState.get('user:1'), {
highlighted: true,
dimmed: false,
})
assert.deepEqual(nodeState.get('node:node-a'), {
highlighted: true,
dimmed: false,
})
assert.deepEqual(nodeState.get('model:gpt-4.1'), {
highlighted: true,
dimmed: false,
})
assert.deepEqual(nodeState.get('channel:101'), {
highlighted: true,
dimmed: false,
})
assert.deepEqual(nodeState.get('user:2'), {
highlighted: false,
dimmed: true,
})
assert.deepEqual(linkState.get('user:1->node:node-a'), {
highlighted: true,
dimmed: false,
})
assert.deepEqual(linkState.get('model:gpt-4.1->channel:101'), {
highlighted: true,
dimmed: false,
})
assert.deepEqual(linkState.get('model:claude-4-sonnet->channel:101'), {
highlighted: false,
dimmed: true,
})
})
test('highlights full paths that traverse the active link', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'root',
activeLink: { source: 'model:gpt-4.1', target: 'channel:101' },
})
const nodeState = new Map(
result.flow.nodes.map((node) => [
node.id,
{ highlighted: node.highlighted, dimmed: node.dimmed },
])
)
const linkState = new Map(
result.flow.links.map((link) => [
`${link.source}->${link.target}`,
{ highlighted: link.highlighted, dimmed: link.dimmed },
])
)
assert.deepEqual(linkState.get('model:gpt-4.1->channel:101'), {
highlighted: true,
dimmed: false,
})
assert.deepEqual(linkState.get('model:gpt-4.1->channel:102'), {
highlighted: false,
dimmed: true,
})
assert.deepEqual(nodeState.get('user:1'), {
highlighted: true,
dimmed: false,
})
assert.deepEqual(nodeState.get('node:node-a'), {
highlighted: true,
dimmed: false,
})
assert.deepEqual(nodeState.get('user:2'), {
highlighted: false,
dimmed: true,
})
})
test('highlights shared aggregate edges when they contain an active path', () => {
const sharedRows: FlowQuotaDataItem[] = [
{
user_id: 1,
username: 'alice',
use_group: 'vip',
channel_id: 101,
channel_name: 'east',
model_name: 'gpt-4.1',
quota: 100,
token_used: 40,
count: 2,
},
{
user_id: 2,
username: 'bob',
use_group: 'vip',
channel_id: 101,
channel_name: 'east',
model_name: 'gpt-4.1',
quota: 50,
token_used: 20,
count: 1,
},
]
const result = buildDashboardFlowData(sharedRows, 'quota', {
role: 'admin',
activeNode: { kind: 'user', id: 'user:1' },
})
const sharedLink = result.flow.links.find(
(link) => link.source === 'group:vip' && link.target === 'model:gpt-4.1'
)
const inactiveUserLink = result.flow.links.find(
(link) => link.source === 'user:2' && link.target === 'group:vip'
)
assert.equal(sharedLink?.value, 150)
assert.equal(sharedLink?.highlighted, true)
assert.equal(sharedLink?.dimmed, false)
assert.equal(inactiveUserLink?.highlighted, false)
assert.equal(inactiveUserLink?.dimmed, true)
})
test('does not emit highlight states without a visible active node', () => {
const withoutActive = buildDashboardFlowData(rows, 'quota', {
role: 'root',
})
const hiddenActive = buildDashboardFlowData(rows, 'quota', {
role: 'root',
visibleStages: ['node', 'token'],
activeNode: { kind: 'user', id: 'user:1' },
})
assert.equal(
withoutActive.flow.nodes.every(
(node) => node.highlighted === undefined && node.dimmed === undefined
),
true
)
assert.equal(
withoutActive.flow.links.every(
(link) => link.highlighted === undefined && link.dimmed === undefined
),
true
)
assert.equal(
hiddenActive.flow.nodes.every(
(node) => node.highlighted === undefined && node.dimmed === undefined
),
true
)
assert.equal(
hiddenActive.flow.links.every(
(link) => link.highlighted === undefined && link.dimmed === undefined
),
true
)
})
test('builds Sankey spec with quota token request tooltips', () => {
const result = buildDashboardFlowData(rows.slice(0, 1), 'quota', {
role: 'root',
})
const flowSpec = buildFlowSankeySpec(result.flow, 'Flow')
const values = flowSpec.data[0].values[0]
const aliceNode = values.nodes.find(
(node: Record) => node.key === 'user:1'
)
const userNodeLink = values.links.find(
(link: Record) =>
link.source === 'user:1' && link.target === 'node:node-a'
)
assert.equal(flowSpec.type, 'sankey')
assert.equal(flowSpec.title.text, 'Flow')
assert.deepEqual(flowSpec.emphasis, { enable: false })
assert.equal(flowSpec.tooltip.mark.visible({ datum: aliceNode }), true)
assert.equal(flowSpec.tooltip.mark.visible({ datum: userNodeLink }), true)
assert.equal(flowSpec.animation, false)
assert.equal(values.nodes.length, 6)
assert.equal(values.links.length, 5)
assert.equal(aliceNode.name, 'alice')
assert.match(userNodeLink.linkColor, /^rgba\(/)
const tooltipRows = flowSpec.tooltip.mark.content
assert.deepEqual(
tooltipRows
.filter((row: Record) =>
typeof row.visible === 'function'
? row.visible({ datum: userNodeLink })
: true
)
.map((row: Record) => [
row.key,
typeof row.value === 'function'
? row.value({ datum: userNodeLink })
: row.value,
]),
[
['Quota', '100'],
['Tokens', '40'],
['Requests', '2'],
['Share', '100.0%'],
]
)
})
test('maps active flow highlight states into the Sankey spec', () => {
const result = buildDashboardFlowData(rows, 'quota', {
role: 'root',
activeNode: { kind: 'user', id: 'user:1' },
})
const flowSpec = buildFlowSankeySpec(result.flow, 'Flow')
const values = flowSpec.data[0].values[0]
const aliceNode = values.nodes.find(
(node: Record) => node.key === 'user:1'
)
const bobNode = values.nodes.find(
(node: Record) => node.key === 'user:2'
)
const highlightedLink = values.links.find(
(link: Record) =>
link.source === 'model:gpt-4.1' && link.target === 'channel:101'
)
const dimmedLink = values.links.find(
(link: Record) =>
link.source === 'model:claude-4-sonnet' && link.target === 'channel:101'
)
const nodeOpacity = flowSpec.node.style.fillOpacity
const linkOpacity = flowSpec.link.style.fillOpacity
assert.deepEqual(flowSpec.emphasis, { enable: false })
assert.equal(aliceNode.highlighted, true)
assert.equal(bobNode.dimmed, true)
assert.equal(highlightedLink.highlighted, true)
assert.equal(dimmedLink.dimmed, true)
assert.equal(nodeOpacity(aliceNode), 1)
assert.equal(nodeOpacity(bobNode), 0.18)
assert.equal(linkOpacity(highlightedLink), 0.86)
assert.equal(linkOpacity(dimmedLink), 0.08)
assert.equal(highlightedLink.zIndex > dimmedLink.zIndex, true)
})
})