Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Use single quotes in generated version.ts file * Update README * Basic `/help` functionality * Update unit tests * Add tests around guild-only commands
- Loading branch information
1 parent
2213b76
commit efc1151
Showing
5 changed files
with
137 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`help presents an ephemeral embed with all available global and guild-bound commands 1`] = ` | ||
Object { | ||
"fields": Array [ | ||
Object { | ||
"name": "\`/help\`", | ||
"value": "Prints the list of commands", | ||
}, | ||
], | ||
"title": "All commands", | ||
} | ||
`; | ||
|
||
exports[`help presents an ephemeral embed with all available global commands 1`] = ` | ||
Object { | ||
"fields": Array [ | ||
Object { | ||
"name": "\`/help\`", | ||
"value": "Prints the list of commands", | ||
}, | ||
], | ||
"title": "All commands", | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,80 @@ | ||
import type { EmbedBuilder } from 'discord.js'; | ||
import { help } from './help'; | ||
|
||
const { allCommands: realAllCommands } = jest.requireActual<typeof import('./index')>('./index'); | ||
const mockAllCommands = new Map<string, Command>(); | ||
|
||
jest.mock('./index', () => ({ | ||
allCommands: mockAllCommands, | ||
})); | ||
|
||
describe('help', () => { | ||
test("it's just a Hello World", async () => { | ||
const mockReply = jest.fn(); | ||
const context = { | ||
const mockReply = jest.fn(); | ||
let context: CommandContext; | ||
|
||
beforeEach(() => { | ||
mockAllCommands.clear(); | ||
realAllCommands.forEach((value, key) => mockAllCommands.set(key, value)); | ||
|
||
context = { | ||
guild: null, | ||
reply: mockReply, | ||
} as unknown as CommandContext; | ||
}); | ||
|
||
test('presents an ephemeral embed with all available global commands', async () => { | ||
context = { ...context, guild: null }; | ||
|
||
await expect(help.execute(context)).resolves.toBeUndefined(); | ||
expect(mockReply).toHaveBeenCalledOnce(); | ||
expect(mockReply).toHaveBeenCalledWith({ | ||
embeds: [expect.toBeObject()], | ||
ephemeral: true, | ||
}); | ||
const call = mockReply.mock.calls[0] as [{ embeds: [EmbedBuilder] }]; | ||
const embed = call[0].embeds[0]; | ||
expect(embed.data.fields).toBeArrayOfSize(mockAllCommands.size); | ||
expect(embed.data).toMatchSnapshot(); | ||
}); | ||
|
||
test('presents an ephemeral embed with all available global and guild-bound commands', async () => { | ||
context = { | ||
...context, | ||
guild: { id: 'the-guild-1234' }, | ||
} as unknown as CommandContext; | ||
|
||
await expect(help.execute(context)).resolves.toBeUndefined(); | ||
expect(mockReply).toHaveBeenCalledOnce(); | ||
expect(mockReply).toHaveBeenCalledWith({ | ||
embeds: [expect.toBeObject()], | ||
ephemeral: true, | ||
}); | ||
const call = mockReply.mock.calls[0] as [{ embeds: [EmbedBuilder] }]; | ||
const embed = call[0].embeds[0]; | ||
expect(embed.data.fields).toBeArrayOfSize(mockAllCommands.size); | ||
expect(embed.data).toMatchSnapshot(); | ||
}); | ||
|
||
test("doesn't show a guild-only command when in DMs", async () => { | ||
const cmd: GuildedCommand = { | ||
name: 'canttouchthis-do-do-do-do', // this test will break if we ever have a command with this name | ||
description: "Can't touch this. (This is a test.)", | ||
requiresGuild: true, | ||
dmPermission: false, | ||
execute() { | ||
// nop | ||
}, | ||
}; | ||
mockAllCommands.set(cmd.name, cmd); | ||
|
||
await expect(help.execute(context)).resolves.toBeUndefined(); | ||
expect(mockReply).toHaveBeenCalledOnce(); | ||
expect(mockReply).toHaveBeenCalledWith('Hello, world!'); | ||
expect(mockReply).toHaveBeenCalledWith({ | ||
embeds: [expect.toBeObject()], | ||
ephemeral: true, | ||
}); | ||
const call = mockReply.mock.calls[0] as [{ embeds: [EmbedBuilder] }]; | ||
const embed = call[0].embeds[0]; | ||
expect(embed.data.fields).toBeArrayOfSize(mockAllCommands.size - 1); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,43 @@ | ||
import { EmbedBuilder } from 'discord.js'; | ||
|
||
export const help: GlobalCommand = { | ||
name: 'help', | ||
description: 'Prints the list of commands', | ||
requiresGuild: false, | ||
async execute({ reply }) { | ||
// TODO: finish this command | ||
await reply('Hello, world!'); | ||
async execute({ guild, reply }) { | ||
// Dynamic import here b/c ./index depends on this file | ||
const { allCommands } = await import('./index'); | ||
|
||
const embed = new EmbedBuilder() // | ||
.setTitle('All commands'); | ||
|
||
function embedCommand(command: Command): void { | ||
embed.addFields({ | ||
name: `\`/${command.name}\``, // i.e. `/help` | ||
value: command.description, | ||
}); | ||
} | ||
|
||
for (const command of allCommands.values()) { | ||
if (guild) { | ||
// We're in a guild. We should check the user's permissions, | ||
// and skip this command if they aren't allowed to use it. | ||
// TODO: Grab the guild's configured permissions for this channel | ||
embedCommand(command); | ||
continue; | ||
} | ||
|
||
// We're in DMs; command should have dmPermission if we're to print it. | ||
// Discord defaults dmPermission to `true`, so `undefined` should behave that way. | ||
// See https://discordjs.guide/interactions/slash-commands.html#dm-permission | ||
if (command.dmPermission === false) continue; | ||
|
||
embedCommand(command); | ||
} | ||
|
||
await reply({ | ||
embeds: [embed], | ||
ephemeral: true, | ||
}); | ||
}, | ||
}; |