Testing your App
How to test your app
This guide shows you how to run unit test on your app.

Requirements

You are required to have the following dependencies. Visit the corresponding sites to follow how to set them up.
This guide is given with the assumption you have some knowledge of:
  • Typescript
  • Basic unit test concepts

App Setup

On your .rcappsconfig add the following lines on the ignoredFiles array:
  1. 1.
    "/mocks/*"
  2. 2.
    "/tests/*"
  3. 3.
    "**/jest.config.js"

Testing

Say for example you have this app command to test:
HelpCommand.ts
1
import { IModify, IRead } from "@rocket.chat/apps-engine/definition/accessors";
2
import { SlashCommandContext } from "@rocket.chat/apps-engine/definition/slashcommands";
3
import { notifyUser } from "../lib/message";
4
import { BoilerplateApp } from "../BoilerplateApp";
5
6
class HelpCommand {
7
public async run({ app, context, read, modify }: { app: BoilerplateApp, context: SlashCommandContext, read: IRead, modify: IModify }): Promise<void> {
8
const room = context.getRoom();
9
const user = context.getSender();
10
11
const text =
12
`\`/boilerplate modal\` Opens a modal\n` +
13
`\`/boilerplate help\` Shows help message`;
14
15
await notifyUser({ app, read, modify, room, user, text });
16
}
17
}
18
19
export const helpCommand = new HelpCommand();
Copied!

Snippet Explanation

It's a very common command that shows a helper to the user on how to use your app. With that in mind let's understand what we want to test and then we will see how.
This class HelpCommand has a single async method called run. Let's dive into this method and see how it works.
On both lines 8 and 9, the method is using the context parameter to get some information regarding room and sender.
On line 11 we just assign a string to a const and on the end of the method it calls a function called notifyUser which send the message to the user.

Testing

At the top of the file, set jest.autoMockOff(); and below will have the example on how to test your command and the explanation of what is happening on each line/block of code.
HelpCommand.spec.ts
1
jest.autoMockOff(); //1
2
const notifyUser = jest.fn();
3
jest.mock('@lib/message', () => ({ //2
4
notifyUser,
5
}));
6
import {
7
commandsMockParams,
8
roomMock,
9
userMock
10
} from '@commands/__mocks__/commands.mock'; //3
11
12
import { helpCommand } from '@commands/HelpCommand'; //4
13
14
describe('HelpCommand', () => { //5
15
test('should set tex with the right values', async () => { //6
16
await helpCommand.run(commandsMockParams); //7
17
const { app, modify, read } = commandsMockParams; //8
18
expect(notifyUser).toBeCalledWith({
19
app,
20
read,
21
modify,
22
room: roomMock,
23
text:
24
`\`/boilerplate modal\` Opens a modal\n` +
25
`\`/boilerplate help\` Shows help message`,
26
user: userMock,
27
}); //9
28
});
29
});
30
Copied!
  1. 1.
    This part is very optional since it depends on how you set your jest.setup.js sometimes auto mock may help and sometimes not;
  2. 2.
    This part covers lines 3..5 which is the part that you will mock the method is called at the end of your method run;
The jest.mock will mock all methods/functions that are inside the path inserted on the parameter and the jest.fn() attributed on notifyUser allows you to test in your test case.
For deep documentation about mock a method please check here.
3. This part is just a form to organize all the mocks you will use on your test, since the run method need some parameters that have a lot of properties you may separate this on a file, below you will see an example:
commands.mock
1
const roomMock = {
2
id: '123',
3
displayName: 'nice display name',
4
slugifiedName: 'slugfied name',
5
type: 'type',
6
creator: {},
7
userIds: ['123', '234'],
8
isDefault: true,
9
isReadOnly: false,
10
displaySystemMessages: true,
11
messageCount: 1,
12
createdAt: 'Mon Nov 22 2021 15:22:49 GMT-0300 (Brasilia Standard Time)',
13
updatedAt: 'Mon Nov 22 2021 15:22:49 GMT-0300 (Brasilia Standard Time)',
14
lastModifiedAt: 'Mon Nov 22 2021 15:22:49 GMT-0300 (Brasilia Standard Time)',
15
description: 'desc',
16
17
};
18
19
const userMock = {
20
id: '567',
21
username: 'username',
22
emails: [],
23
type: 'nice type',
24
isEnabled: true,
25
name: 'name',
26
roles: 'admin',
27
status: 'Registered',
28
statusConnection: 'Online',
29
utcOffset: 'ZM',
30
createdAt: 'Mon Nov 22 2021 15:22:49 GMT-0300 (Brasilia Standard Time)',
31
updatedAt: 'Mon Nov 22 2021 15:22:49 GMT-0300 (Brasilia Standard Time)',
32
lastLoginAt: 'Mon Nov 22 2021 15:22:49 GMT-0300 (Brasilia Standard Time)',
33
appId: '678',
34
};
35
const commandsMockParams: {
36
app: WikipediaApp,
37
context: SlashCommandContext,
38
read: IRead,
39
modify: IModify,
40
http: IHttp
41
} = {
42
app: {
43
initialize: jest.fn(),
44
} as unknown as WikipediaApp,
45
context: {
46
getSender: jest.fn().mockReturnValue(userMock),
47
getRoom: jest.fn().mockReturnValue(roomMock),
48
getArguments: jest.fn().mockReturnValue(args),
49
getThreadId: jest.fn(),
50
getTriggerId: jest.fn(),
51
} as unknown as SlashCommandContext,
52
.
53
.
54
.
55
.
56
.
Copied!
4. This part you only need to import the function or class that needs to be tested;
5. Here you set your describe to identify your test, for this example HelpCommand is fine;
6. This part is where the shows start, you will describe your tests cases, for this example, one is enough but it can be more, thinking that you may need to test multiples cases as errors or forks.
The test receives a string and a callback to run the test.
In some cases, the method/function that you are testing may be a Promise, so you can set the callback as async it will work in most of the cases, but some not, so for more information about testing async methods, please reach this link
7. This line you only need to call your method/function and in this particular case this is a void method it will be no need to attribute the result of your method in a variable;
8. This part only takes all the mocked values to check our methods;
9. This is the famous expect where you check if your method is working as it is supposed to do, in this case, we are checking if the notifyUser is been called with the right parameters.

Running your test

Run your test by following any of the two procedures
  • Using Terminal: Open up your terminal in the working directory and execute jest <file-name> or just jest to run all test files;
  • Using the VScode extension: You only need to install this vscode extension and all of your tests files will look like this:
Using extension to run the tests
Two buttons will appear upon tests and describes so you can click run or debug and if everything went well you may face something like this:
All tests succeed
For more information on how to run your tests please visit this link.

Conclusion

This docs does not show all you can do with jest. Feel free to check out Jest documentation for other samples.
Last modified 1mo ago