Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions packages/bot/src/functions/general/commands/help.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import { describe, test, expect, jest, beforeEach } from '@jest/globals'

jest.mock('@lucky/shared/utils', () => ({
debugLog: jest.fn(),
infoLog: jest.fn(),
errorLog: jest.fn(),
}))

jest.mock('../../../utils/general/interactionReply.js', () => ({
interactionReply: jest.fn(),
}))

jest.mock('../../../utils/command/commandCategory.js', () => ({
getCommandCategory: (cmd: any) => cmd.category || 'general',
getAllCategories: () => [
{ key: 'general', label: 'General' },
{ key: 'music', label: 'Music' },
{ key: 'moderation', label: 'Moderation' },
],
}))

import helpCommand from './help.js'

function createClient() {
return {
user: {
displayAvatarURL: () => 'https://example.com/bot-avatar.png',
},
commands: new Map([
[
'help',
{
data: { name: 'help', description: 'Show all commands' },
category: 'general',
},
],
[
'play',
{
data: { name: 'play', description: 'Play music' },
category: 'music',
},
],
[
'ban',
{
data: { name: 'ban', description: 'Ban a user' },
category: 'moderation',
},
],
]),
}
}

function createInteraction() {
return {
user: {
id: 'user-123',
tag: 'TestUser#1234',
displayAvatarURL: () => 'url',
},
reply: jest.fn(),
editReply: jest.fn(),
}
}

describe('help command', () => {
beforeEach(() => {
jest.clearAllMocks()
})

test('command name is "help"', () => {
expect(helpCommand.data.name).toBe('help')
})

test('command has proper description', () => {
expect(helpCommand.data.description).toContain('Show all available')
})

test('command category is "general"', () => {
expect(helpCommand.category).toBe('general')
})

test('has execute function', () => {
expect(typeof helpCommand.execute).toBe('function')
})

test('executes with valid client and interaction', async () => {
const client = createClient()
const interaction = createInteraction()

await helpCommand.execute({
client,
interaction,
} as any)
})

test('builds categories from client commands', async () => {
const client = createClient()
const interaction = createInteraction()

await helpCommand.execute({
client,
interaction,
} as any)

// Command completed without error, no exception thrown
expect(true).toBe(true)
})

test('handles null client.user gracefully', async () => {
const client = {
user: null,
commands: new Map([
[
'test',
{
data: { name: 'test', description: 'test' },
category: 'general',
},
],
]),
}
const interaction = createInteraction()

await helpCommand.execute({
client,
interaction,
} as any)
})

test('handles empty commands map', async () => {
const client = {
user: { displayAvatarURL: () => 'url' },
commands: new Map(),
}
const interaction = createInteraction()

await helpCommand.execute({
client,
interaction,
} as any)
})

test('handles error when commands iteration fails', async () => {
const client = {
user: { displayAvatarURL: () => 'url' },
commands: null,
}
const interaction = createInteraction()

await helpCommand.execute({
client,
interaction,
} as any)
})

test('handles multiple commands in same category', async () => {
const client = {
user: { displayAvatarURL: () => 'url' },
commands: new Map([
[
'cmd1',
{
data: { name: 'cmd1', description: 'First command' },
category: 'general',
},
],
[
'cmd2',
{
data: { name: 'cmd2', description: 'Second command' },
category: 'general',
},
],
]),
}
const interaction = createInteraction()

await helpCommand.execute({
client,
interaction,
} as any)
})
})
154 changes: 154 additions & 0 deletions packages/bot/src/functions/general/commands/reactionrole.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { describe, test, expect, jest, beforeEach } from '@jest/globals'

jest.mock('@lucky/shared/utils', () => ({
errorLog: jest.fn(),
}))

jest.mock('@lucky/shared/services', () => ({
reactionRolesService: {
createReactionRoleMessage: jest.fn(),
deleteReactionRoleMessage: jest.fn(),
listReactionRoleMessages: jest.fn(),
},
}))

jest.mock('../../../utils/general/interactionReply.js', () => ({
interactionReply: jest.fn(),
}))

jest.mock('../../../utils/command/commandValidations.js', () => ({
requireGuild: async (interaction: any) => {
return interaction.guild !== null
},
}))

jest.mock('../../../utils/general/embeds.js', () => ({
errorEmbed: (title: string, desc: string) => ({
data: { title, description: desc },
}),
successEmbed: (title: string, desc: string) => ({
data: { title, description: desc },
}),
}))

jest.mock('../handlers/reactionroleHandlers.js', () => ({
handleCreate: jest.fn(),
handleDelete: jest.fn(),
handleList: jest.fn(),
}))

import reactionroleCommand from './reactionrole.js'

function createGuild(id = 'guild-123') {
return { id }
}

function createInteraction({
guildId = 'guild-123',
guild = null as any,
subcommand = 'list',
} = {}) {
const interaction = {
guild: guild || createGuild(guildId),
guildId,
options: {
getSubcommand: jest.fn(() => subcommand),
},
}
return interaction as any
}

describe('reactionrole command', () => {
beforeEach(() => {
jest.clearAllMocks()
})

test('command name is "reactionrole"', () => {
expect(reactionroleCommand.data.name).toBe('reactionrole')
})

test('command has reaction role description', () => {
expect(reactionroleCommand.data.description).toContain('reaction role')
})

test('command category is "general"', () => {
expect(reactionroleCommand.category).toBe('general')
})

test('command requires ManageRoles permission', () => {
const perms = reactionroleCommand.data.default_member_permissions
expect(perms).toBeDefined()
})

test('has create subcommand', () => {
const createSub = reactionroleCommand.data.options.find(
(opt: any) => opt.name === 'create',
)
expect(createSub).toBeDefined()
})

test('has delete subcommand', () => {
const deleteSub = reactionroleCommand.data.options.find(
(opt: any) => opt.name === 'delete',
)
expect(deleteSub).toBeDefined()
})

test('has list subcommand', () => {
const listSub = reactionroleCommand.data.options.find(
(opt: any) => opt.name === 'list',
)
expect(listSub).toBeDefined()
})

test('has execute function', () => {
expect(typeof reactionroleCommand.execute).toBe('function')
})

test('executes create subcommand in guild', async () => {
const interaction = createInteraction({ subcommand: 'create' })

await reactionroleCommand.execute({ interaction } as any)
})

test('executes delete subcommand in guild', async () => {
const interaction = createInteraction({ subcommand: 'delete' })

await reactionroleCommand.execute({ interaction } as any)
})

test('executes list subcommand in guild', async () => {
const interaction = createInteraction({ subcommand: 'list' })

await reactionroleCommand.execute({ interaction } as any)
})

test('rejects command outside of guild', async () => {
const interaction = {
guild: null,
guildId: null,
options: { getSubcommand: jest.fn(() => 'list') },
}

await reactionroleCommand.execute({ interaction } as any)
})

test('returns early if guild is null after validation', async () => {
const interaction = {
guild: null,
guildId: 'guild-123',
options: { getSubcommand: jest.fn(() => 'create') },
}

await reactionroleCommand.execute({ interaction } as any)
})

test('handles all subcommands', async () => {
const subcommands = ['create', 'delete', 'list']

for (const subcommand of subcommands) {
const interaction = createInteraction({ subcommand })
await reactionroleCommand.execute({ interaction } as any)
}
})
})
Loading
Loading