Skip to content

Testing

Tatiana edited this page Mar 29, 2021 · 6 revisions

All bot commands must be tested. 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 in the same formatting as the above */
      ['/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 begin and end with whitespace as their own separate 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 - read more [here](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()
      // If your command behaves differently based on mentions being passed in
     // NOTE: This "it" block MUST use an async callback for these snapshots to be generated properly
      expect(await command.cb(generateMentions(0))).toMatchSnapshot();
      expect(await command.cb(generateMentions(1))).toMatchSnapshot();
      expect(await command.cb(generateMentions(2))).toMatchSnapshot();
      expect(await command.cb(generateMentions(3))).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.

If your particular command requires mentions to be passed into the callback, you may use the generateMentions helper located inside of mockData.js, which dynamically creates Discord User objects for you to leverage in your tests.

Clone this wiki locally