• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

VolvoxLLC / volvox-bot / 24063007086

07 Apr 2026 03:36AM UTC coverage: 90.395% (-0.2%) from 90.557%
24063007086

Pull #443

github

web-flow
Merge a2f8be6dd into d130899e6
Pull Request #443: feat(xp): add dashboard editor for level-up actions

6826 of 8020 branches covered (85.11%)

Branch coverage included in aggregate %.

40 of 49 new or added lines in 3 files covered. (81.63%)

4 existing lines in 3 files now uncovered.

11498 of 12251 relevant lines covered (93.85%)

217.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.64
/src/modules/actions/normalizeAction.js
1
/**
2
 * XP action normalization helpers.
3
 * Bridges legacy config payloads and the richer dashboard action editor shape.
4
 */
5

6
function normalizeEmbed(embed) {
7
  if (!embed || typeof embed !== 'object' || Array.isArray(embed)) {
1!
NEW
8
    return undefined;
×
9
  }
10

11
  const normalized = {
1✔
12
    title: typeof embed.title === 'string' ? embed.title : '',
1!
13
    description: typeof embed.description === 'string' ? embed.description : '',
1!
14
    color: embed.color,
15
    thumbnail: undefined,
16
    fields: Array.isArray(embed.fields)
1!
17
      ? embed.fields
18
          .map((field) => ({
1✔
19
            name: typeof field?.name === 'string' ? field.name : '',
1!
20
            value: typeof field?.value === 'string' ? field.value : '',
1!
21
            inline: Boolean(field?.inline),
22
          }))
23
          .filter((field) => field.name || field.value)
1!
24
      : [],
25
    footer: undefined,
26
    image: typeof embed.image === 'string' ? embed.image : undefined,
1!
27
    timestamp: embed.timestamp === true,
28
  };
29

30
  if (typeof embed.thumbnail === 'string') {
1!
NEW
31
    normalized.thumbnail = embed.thumbnail;
×
32
  } else if (embed.thumbnailType === 'user_avatar') {
1!
33
    normalized.thumbnail = '{{avatar}}';
1✔
NEW
34
  } else if (embed.thumbnailType === 'server_icon') {
×
NEW
35
    normalized.thumbnail = '{{serverIcon}}';
×
NEW
36
  } else if (embed.thumbnailType === 'custom' && typeof embed.thumbnailUrl === 'string') {
×
NEW
37
    normalized.thumbnail = embed.thumbnailUrl;
×
38
  }
39

40
  if (typeof embed.footer === 'string') {
1!
NEW
41
    normalized.footer = { text: embed.footer };
×
42
  } else if (embed.footer && typeof embed.footer === 'object' && !Array.isArray(embed.footer)) {
1!
NEW
43
    normalized.footer = {
×
44
      text: typeof embed.footer.text === 'string' ? embed.footer.text : '',
×
45
      iconURL: typeof embed.footer.iconURL === 'string' ? embed.footer.iconURL : undefined,
×
46
    };
47
  } else if (typeof embed.footerText === 'string' || typeof embed.footerIconUrl === 'string') {
1!
48
    normalized.footer = {
1✔
49
      text: typeof embed.footerText === 'string' ? embed.footerText : '',
1!
50
      iconURL: typeof embed.footerIconUrl === 'string' ? embed.footerIconUrl : undefined,
1!
51
    };
52
  }
53

54
  if (typeof embed.imageUrl === 'string' && !normalized.image) {
1!
55
    normalized.image = embed.imageUrl;
1✔
56
  }
57

58
  if (embed.showTimestamp === true) {
1!
59
    normalized.timestamp = true;
1✔
60
  }
61

62
  return normalized;
1✔
63
}
64

65
/**
66
 * Normalize a single XP action into the runtime shape expected by handlers.
67
 *
68
 * @param {Object} action
69
 * @returns {Object}
70
 */
71
export function normalizeXpAction(action) {
72
  if (!action || typeof action !== 'object') {
28!
NEW
73
    return action;
×
74
  }
75

76
  const normalized = { ...action };
28✔
77

78
  if (typeof normalized.message === 'string' && !normalized.template) {
28✔
79
    normalized.template = normalized.message;
1✔
80
  }
81

82
  if (
28✔
83
    normalized.type === 'nickPrefix' &&
30✔
84
    typeof normalized.prefix === 'string' &&
85
    !normalized.template
86
  ) {
87
    normalized.template = normalized.prefix;
1✔
88
  }
89

90
  if (
28✔
91
    normalized.type === 'nickSuffix' &&
30✔
92
    typeof normalized.suffix === 'string' &&
93
    !normalized.template
94
  ) {
95
    normalized.template = normalized.suffix;
1✔
96
  }
97

98
  if (normalized.embed) {
28✔
99
    normalized.embed = normalizeEmbed(normalized.embed);
1✔
100
  }
101

102
  return normalized;
28✔
103
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc