Testing JavaScript with Jest on Vultr
Jest is a popular JavaScript testing framework used for testing React and JavaScript codebases. It offers a comprehensive set of matchers for making assertions, allowing users to write tests for many different types of projects. Jest organizes tests into test suites; this structured approach improves both maintainability and readability, leading to more efficient testing workflows.
In this article, we'll explore the various types of tests commonly used in software development and share some good practices and conventions for testing. We'll write JavaScript functions and test them using the Jest testing framework on a Vultr server with the NodeJS marketplace application.
Types of tests
To ensure code quality and functionality, development typically involves three types of tests. Each type serves a specific purpose:
-
Unit tests: These tests focus on testing individual units or components, such as functions, methods, or classes. This type of testing ensures that each code component functions correctly on its own.
-
Integration tests: These tests focus on assessing whether different components of the application interact with each other as expected. Unlike unit tests, which test a single component, these tests involve interactions between multiple units to ensure they function as expected when combined.
-
End-to-end tests: These tests simulate real user scenarios by testing the application flow from start to finish. These tests are usually automated and interact with the application like a real user, ensuring that the application works as intended in real-world situations.
Testing conventions
The Arrange-Act-Assert (AAA) pattern is a commonly used convention used to organize and structure unit test cases.
To understand each part, here's an example where we want to test if user emails are alphanumeric (letters and numbers) and use the example.com
domain:
test("returns false for an invalid domain", () => {
const email = "user123@example.net";
const result = isValidEmail(email);
expect(result).toBe(false);
});
-
Arrange: In this phase, you set up the initial condition and prepare the test environment. This includes initializing objects, setting up inputs, and configuring the environment to create the scenario you wish to test. In the above example, we want to test if the
isValidEmail
function correctly identifies invalid emails. We've initialized theemail
variable with a string that does not meet our email criteria because it uses the.net
TLD instead of.com
. -
Act: In this phase, you perform the action or behavior that you want to test. This could involve calling a method, interacting with an object, or executing a specific piece of code. In the above example, this step involves calling the
isValidEmail
function and passing it theemail
variable as an argument. -
Assert: Finally, in this phase, you verify that the outcome of the "Act" phase meets your expectations. In the above example, we've used the
expect
function, provided by the Jest framework, to confirm that theresult
returned by theisValidEmail
function is correctly identified asfalse
, as expected for an invalid email.
Setting up the project directory on Vultr
To begin, deploy a server by following the steps in the section Deploying a server on Vultr in our previous article. Ensure that you select NodeJS in the Marketplace Apps tab. Next, let's proceed to set up a Node.js project and install the Jest framework. We'll then define two functions in separate JavaScript files, which we'll test in the subsequent sections.
-
Verify the Node.js installation by using the following command:
bashnode --version
-
Create a project directory, and navigate into it.
bashmkdir sample cd sample
-
Initialize a Node.js project.
bashnpm init -y
-
Install the Jest testing framework.
bashnpm install --save-dev jest
The
--save-dev
flag is used to specify that the package is installed as a development dependency. This means that it will be used only during development and testing phases, not for production. -
Open the
package.json
file. We're using the Nano text editor. Check the shortcuts cheatsheet for help using Nano.bashnano package.json
-
Add a test script.
json"scripts": { "test": "jest" }
-
Save and exit the file (Ctrl + X to close the file, Y when prompted to save the changes).
-
Create a JavaScript file.
bashnano token.js
-
Copy and paste the code below into the
token.js
file. This code demonstrates how to calculate the expiry date of a JSON Web Token (JWT) and check if it has expired.Note: The hand-written expiry check shown here is purely for illustration purposes. When handling authentication tokens in real-world projects, relying on well-established libraries, such as jsonwebtoken, is strongly recommended.
javascript/** * * @param {string} token * @returns {Date} */ function getTokenExpiryDate(token) { if (!token) return null; const tokenParts = token.split("."); const payload = tokenParts[1]; const decodedPayload = Buffer.from(payload, "base64").toString(); const payloadObject = JSON.parse(decodedPayload); const expiryDate = new Date(payloadObject.exp * 1000); return expiryDate; } /** * * @param {string} token * @returns {boolean} */ function isTokenExpired(token) { const expiryDate = getTokenExpiryDate(token); const currentDate = new Date(); return currentDate > expiryDate; } module.exports = { isTokenExpired };
The code above defines two functions,
getTokenExpiryDate
andisTokenExpired
, which calculate the expiry date of the provided JWT token and returntrue
orfalse
based on the expiration status of the token. -
Save and exit the file.
-
Create another JavaScript file.
bashnano email.js
-
Copy and paste the following code into the file:
javascriptfunction isValidEmail(email) { const emailRegex = /[a-zA-Z0-9]+@example\.com/; return emailRegex.test(email); } module.exports = { isValidEmail };
The code above defines an
isValidEmail
function that validates the structure of the provided email using a regex. The regular expression lets us verify that all emails are alphanumeric and end with exactly@example.com
. -
Save and exit the file.
Writing unit tests with Jest
In this section, you'll learn how to write unit tests for the JavaScript functions defined earlier by using the Jest framework. We'll place these tests in a separate directory within the same project. We recommend that you follow the file naming conventions demonstrated here because Jest automatically treats files ending in .test.js
as test files.
-
Within the
sample
directory, create another directory calledtests
and navigate into it.bashmkdir tests cd tests
-
Create a JavaScript test file.
bashnano token.test.js
-
Copy and paste the following code into the file:
javascriptconst { isTokenExpired } = require("/root/sample/token.js"); describe("isTokenExpired", () => { test("should return false if the token is not expired", () => { const token = "eyJ0eXAiOiJKV1QiLCJhbGciOi..."; const result = isTokenExpired(token); expect(result).toBe(false); }); test("should return true if the token is expired", () => { const token = "eyJ0eXAiOiJKV1QiLCJhbGciOi..."; const result = isTokenExpired(token); expect(result).toBe(true); }); });
The code above uses the
isTokenExpired
function defined earlier to determine if the function is behaving as expected, returning the correct boolean value based on whether a JWT is expired or not.Note: If you want the
isTokenExpired
function to check real tokens, you can generate expired and non-expired JWTs using a JSON Web Token Builder and use them instead of the placeholders in the tests above. -
Save and exit the file.
-
Create another JavaScript test file.
bashnano email.test.js
-
Copy and paste the following code into the file:
javascriptconst { isValidEmail } = require("/root/sample/email.js"); describe("isValidEmail", () => { test("returns true for a valid email", () => { const email = "user123@example.com"; const result = isValidEmail(email); expect(result).toBe(true); }); test("returns false for an invalid domain", () => { const email = "user123@example.net"; const result = isValidEmail(email); expect(result).toBe(false); }); });
The code above uses the
isValidEmail
function defined earlier and tests it by providing a valid and an invalid email. It checks the validation results by matching the expected output with the actual output. -
Save and exit the file.
Running Jest tests on Vultr
In this section, you'll learn how to run tests using the Jest framework by applying two approaches. In the first method, we'll run individual unit tests for each function defined in the previous sections. In the second method, we'll run tests for both the functions simultaneously.
Running individual unit tests
-
Run the token validation tests.
bashnpm test -- tests/token.test.js
If the tests pass successfully, your output will look as shown below:
> sample@1.0.0 test > jest tests/token.test.js PASS tests/token.test.js isTokenExpired ✓ should return false if the token is not expired (2 ms) ✓ should return true if the token is expired (1 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 0.315 s, estimated 1 s Ran all test suites matching /tests\/token.test.js/i.
-
Next, run the email validation tests.
bashnpm test -- tests/email.test.js
If the tests pass successfully, your output will look as shown below:
> sample@1.0.0 test > jest tests/email.test.js PASS tests/email.test.js isValidEmail ✓ returns true for a valid email (2 ms) ✓ returns false for an invalid domain (1 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total Time: 0.451 s Ran all test suites matching /tests\/email.test.js/i.
Running all tests together
Run all the tests together by using the following command:
npm test
If the tests pass successfully, your output will look as shown below:
> sample@1.0.0 test > jest PASS tests/email.test.js PASS tests/token.test.js Test Suites: 2 passed, 2 total Tests: 4 passed, 4 total Snapshots: 0 total Time: 0.225 s, estimated 1 s Ran all test suites.
Conclusion
In this article, we looked at various types of tests and testing conventions. We explored how to write and run unit tests for functions using Jest on a Vultr server with Node.js pre-installed. By leveraging tools like Jest, you can enhance the reliability and robustness of your code, to develop more stable and maintainable software.
This is a sponsored article by Vultr. Vultr is the world's largest privately-held cloud computing platform. A favorite with developers, Vultr has served over 1.5 million customers across 185 countries with flexible, scalable, global Cloud Compute, Cloud GPU, Bare Metal, and Cloud Storage solutions. Learn more about Vultr.