Skip to content

Testing

mao-sz edited this page Sep 8, 2025 · 11 revisions

Slash commands do not need individual testing unless they contain code that extends or alters the functionality of the Discord.js library, or is outside of the standard implementations. Everything else will need to be tested with a variety of test cases. If you are unsure of what needs to be tested, just ask.

Below is an example of what testing we would need for a non-slash command (AKA 'Legacy' or "! commands"):

For each command file you create, you will also need to create a <command>.test.js file. You will need to ensure that the regex, as well as the callback, are tested with a variety of test cases.

Each spec file will need to test for the regex and the callback using the following format:

const command = require('./command')

describe('/commandname', () => {
  describe('regex', () => {
    /* Jest requires an array of arrays (also called a table) to be passed in so we may test each string with the same case
    For more information: https://jestjs.io/docs/en/api#testeachtablename-fn-timeout */
    it.each([
      ['/string'],
      [' /string'],
      ['/string @odin-bot'],
      ['@odin-bot /string'],
    ])('correct strings trigger the callback', (string) => {
      expect(command.regex.test(string)).toBeTruthy()
    })
    
    it.each([
     /* Incorrect variations of the string such as typos, misspellings, similar words, etc */
      ['/strng'],
      ['/strong'],
      ['/strings],
      ['string'],
    ])("'%s' does not trigger the callback", (string) => {
      expect(command.regex.test(string)).toBeFalsy()
    })

    // We also want to check to see if commands can be called from anywhere in a message
    it.each([
      ['Check this out! /string'],
      ['Don\'t worry about /string'],
      ['Hey @odin-bot, /string'],
      ['/@odin-bot ^ /me /time /string$*']
    ])("'%s' - command can be anywhere in the string", (string) => {
      expect(command.regex.test(string)).toBeTruthy()
    })
    
    // Commands should not trigger unless they are their own distinct phrase or word
    it.each([
      ['@user/string'],
      ['it\'s about/string'],
      ['/stringsanillusion'],
      ['/string/'],
      ['/string*'],
      ['/string...']
    ])("'%s' - command should be its own word/group - no leading or trailing characters", (string) => {
      expect(command.regex.test(string)).toBeFalsy()
    })
  })
  
  // This generates a snapshot test - https://jestjs.io/docs/snapshot-testing#:~:text=Snapshot%20tests%20are%20a%20very,file%20stored%20alongside%20the%20test
  describe('callback', () => {
    it('returns correct output', () => {
      expect(command.cb()).toMatchSnapshot()
    })
  })
})

Once you have filled out your test suite, make sure you have saved <command>.js, then run npm test <command>.test.js to ensure all tests for your command pass and a snapshot is generated in the __snapshots__ directory. If your command produces a different output based on number of mentions, or other variable factors in a message, such as the user calling the command, server roles, etc, you must create snapshots for each of these scenarios. Once you have confirmed that your snapshot file matches the correct output, you may submit a pull request for review. Your tests must pass in order for your pull request to be merged.

NOTE: If your changes alters the output of a command, you can run npm test -- -u to update the corresponding snapshot. You must verify that your snapshots match the expected output.

Clone this wiki locally