team-tree.test.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /**
  2. * Tests for cfc-frontend utils/team-tree.js
  3. *
  4. * Tests the pure function that converts flat /api/commission/team/tree nodes
  5. * (as returned by the backend) into preorder rows usable by the tree view.
  6. * These are pure functions - no uni mock needed.
  7. */
  8. describe('team-tree.js', () => {
  9. let teamTree
  10. beforeAll(() => {
  11. teamTree = require('@/utils/team-tree')
  12. })
  13. describe('buildTeamTreeRows', () => {
  14. const nodes = [
  15. { userId: 101, nickname: '直推A', level: 1, parentId: 100, memberConsumption: 32000, myCfEarnedFromMember: 9600 },
  16. { userId: 102, nickname: '间推B', level: 2, parentId: 101, memberConsumption: 8000, myCfEarnedFromMember: 2400 },
  17. { userId: 103, nickname: '直推C', level: 1, parentId: 100, memberConsumption: 15000, myCfEarnedFromMember: 4500 }
  18. ]
  19. test('builds preorder rows with depth from flat nodes', () => {
  20. const rows = teamTree.buildTeamTreeRows(nodes)
  21. expect(rows.map(r => r.node.userId)).toEqual([101, 102, 103])
  22. expect(rows.map(r => r.depth)).toEqual([0, 1, 0])
  23. })
  24. test('marks hasChildren and collapsed flags', () => {
  25. const rows = teamTree.buildTeamTreeRows(nodes)
  26. expect(rows[0].hasChildren).toBe(true)
  27. expect(rows[0].collapsed).toBe(false)
  28. expect(rows[1].hasChildren).toBe(false)
  29. expect(rows[2].hasChildren).toBe(false)
  30. })
  31. test('collapsed node hides its descendants only', () => {
  32. const rows = teamTree.buildTeamTreeRows(nodes, [101])
  33. expect(rows.map(r => r.node.userId)).toEqual([101, 103])
  34. expect(rows[0].collapsed).toBe(true)
  35. })
  36. test('treats nodes with unknown parentId as roots', () => {
  37. const rows = teamTree.buildTeamTreeRows(nodes)
  38. expect(rows.filter(r => r.depth === 0).length).toBe(2)
  39. })
  40. test('prefers referrerId over parentId for immediate parent (materialized tree)', () => {
  41. // /api/commission/team/tree 物化表查询结果中 parentId 恒为根节点,referrerId 才是直接上级
  42. const materialized = [
  43. { userId: 101, referrerId: 100, parentId: 100, level: 1 },
  44. { userId: 102, referrerId: 101, parentId: 100, level: 2 }
  45. ]
  46. const rows = teamTree.buildTeamTreeRows(materialized)
  47. expect(rows.map(r => r.node.userId)).toEqual([101, 102])
  48. expect(rows.map(r => r.depth)).toEqual([0, 1])
  49. expect(rows[0].hasChildren).toBe(true)
  50. expect(rows[1].hasChildren).toBe(false)
  51. })
  52. test('rootUserId shifts root depth so "self" row can sit at depth 0', () => {
  53. // team.vue 自造根行(depth=0),传入 rootUserId 后 L1 成员 depth 从 1 开始
  54. const materialized = [
  55. { userId: 101, referrerId: 100, parentId: 100, level: 1 },
  56. { userId: 102, referrerId: 101, parentId: 100, level: 2 }
  57. ]
  58. const rows = teamTree.buildTeamTreeRows(materialized, [], 100)
  59. expect(rows.map(r => r.node.userId)).toEqual([101, 102])
  60. expect(rows.map(r => r.depth)).toEqual([1, 2])
  61. })
  62. test('returns empty array for empty nodes', () => {
  63. expect(teamTree.buildTeamTreeRows([])).toEqual([])
  64. expect(teamTree.buildTeamTreeRows(null)).toEqual([])
  65. expect(teamTree.buildTeamTreeRows(undefined)).toEqual([])
  66. })
  67. test('guards against self-referencing cycles', () => {
  68. const cyclic = [
  69. { userId: 201, nickname: 'A', level: 1, parentId: 201 }
  70. ]
  71. const rows = teamTree.buildTeamTreeRows(cyclic)
  72. expect(rows.length).toBe(1)
  73. expect(rows[0].depth).toBe(0)
  74. })
  75. })
  76. })