Start tracking your progress
Trailhead Home
Trailhead Home

Mock Other Components

Learning Objectives

After completing this unit, you’ll be able to:

  • Describe the stubs provided by the sfdx-lwc-jest package.
  • Understand how to override the Jest config.
  • Test components outside your development environment.
  • Create stubs for external components.

Mocking Base Components

The sfdx-lwc-jest package lets us run Jest on Lightning Web Components. It sets up all the necessary Jest configs to run tests without any additional changes. We’ve been using it extensively in the prior modules. This package includes a set of stubs (programs that simulate components that a module undergoing tests depends on) for all components in the Lightning namespace. This includes all the Lightning Base Components. The stubs are installed in the src/lightning-stubs directory in the node-modules/@salesforce/sfdx-lwc-jest directory.

lightning-stubs directory in the test-lwc project.

There may be times when you need to override the default stubs provided. This is done by overriding the Jest configs and then creating custom stubs. Let's go through the steps of doing this for lightning-button.

Start by setting up the directories for the custom stubs in Visual Studio Code.

  1. Right-click the force-app directory and select New Folder.
  2. Enter test for the name of the new directory.
  3. Right-click the new test directory and select New Folder.
  4. Enter jest-mocks for the name of the new directory.
  5. Right-click the new jest-mocks directory and select New Folder.
  6. Enter lightning for the name of the new directory.

This is the root for Lightning Base Component stubs.

Next, override the Jest config by updating the file named jest.config.js at the root of your Salesforce DX project and importing the default config from sfdx-lwc-jest.

  1. Open the jest.config.js file.
  2. Enter the following code block into the new file after the “add any custom configurations here” comment:
      moduleNameMapper: {
        '^lightning/button$': '<rootDir>/force-app/test/jest-mocks/lightning/button'
      }
    Notice the moduleNameMapper. This is telling Jest where to find the stub for lightning-button. The first dash is converted to a forward slash and the rest of the component name goes from kebab to camel case. The reason for the forward slash is because the module resolver treats everything before the first dash as the namespace. Here, <rootDir> maps to the root of the Salesforce DX workspace.
  3. Save the file.

Now let's add the button stub to the lightning directory we just created.

  1. Right-click the lightning directory we created in the last steps and select New File.
  2. Enter button.html for the name of the new file.
  3. Enter the following code block into the new file:
    <template></template>
  4. Save the file.
  5. Right-click the lightning directory and select New File.
  6. Enter button.js for the name of the new file.
  7. Enter the following code block into the new file:
    import { LightningElement, api } from 'lwc';
      
    export default class Button extends LightningElement {
      @api disabled;
      @api iconName;
      @api iconPosition;
      @api label;
      @api name;
      @api type;
      @api value;
      @api variant;
    }
  8. Save the file.

These two files are copies of the lightning-button files from the lightning-stubs folder. They allow for overriding the base lightning-button for Jest tests if needed.

We can now override the default stubs provided by sfdx-lwc-jest. What about components from other namespaces or managed packages? We can handle those cases with just a couple of adjustments. Let’s dig into that next.

Mocking Other Components

Let’s start with mocking components with a different namespace. To do this, you set up a Lightning web component with a Jest test that fails and then we’ll mock out a fix.

  1. Create a new Lightning web component in Visual Studio Code.
  2. Set the name to otherComponents.
  3. Now for a different way to create the Jest test. Run this CLI command in the terminal:
    sfdx force:lightning:lwc:test:create -f force-app/main/default/lwc/otherComponents/otherComponents.js

This command automatically creates the __tests__ folder and the otherComponents.test.js test file. Notice that the imports are already there and the initial describe block is there with an initial failing test. 

Running that test fails because we expected 1 to be 2. Let’s fix that so we can see how the other components error when they aren’t stubbed out.

  1. Open the test file otherComponents.test.js and update the test to expect 1 to be 1:
    expect(1).toBe(1);
  2. Save the file and run the test.
  3. The test passes.

Now let’s add a component with a different namespace to the LWC.

  1. Open the otherComponents.html file and add this code between the template tags:
    <thunder-hammer-button onclick={makeNoise}></thunder-hammer-button>
  2. Save the file and run the test.
  3. The test fails for a new reason:
    Test suite failed to run
      Cannot find module 'thunder/hammerButton' from 'otherComponents.html'

Since the <thunder-hammer-button> component is from another namespace, and not in the local lwc directory, you need to create a stub and update the Jest config to map the name of these components to the mock file.

First you need to add a thunder directory to represent the namespace. Then you add the files to stub it out.

  1. Right-click the jest-mocks directory in force-app/test/ directory and select New Folder.
  2. Enter thunder for the name of the new directory.
  3. Right-click the thunder directory and select New File.
  4. Enter hammerButton.html for the name of the new file.
  5. Enter the following code block into the new file:
    <template></template>
  6. Save the file.
  7. Right-click the new thunder directory and select New File.
  8. Enter hammerButton.js for the name of the new file.
  9. Enter the following code block into the new file:
    import { LightningElement, api } from 'lwc';
      
    export default class HammerButton extends LightningElement {
      @api label;
      // any other implementation you may want to expose here
    }
  10. Save the file and run the test.
  11. The test fails. We need to update the Jest config file.
  12. Open jest.config.js and add this line right under the moduleNameMapper: { line:
    '^thunder/hammerButton$': '<rootDir>/force-app/test/jest-mocks/thunder/hammerButton',
  13. Save the file and run the test.
  14. Awesome! The test passes.

There will be times when the LWC you are working with imports another LWC that is not in the local LWC directory of your Salesforce DX project. Either because it is part of a managed package or it didn’t get downloaded with the source files. Without a stub they will cause Jest to fail. Let’s test that.

  1. Open the otherComponents.html file and add this code after the first template tag:
    <c-display-panel errors={error} notes={messages}></c-display-panel>
  2. Save the file and run the test.
  3. The test fails since it can’t find the component.

You can fix that with a stub. You start by creating the stub and then updating the Jest config.

  1. Right-click the jest-mocks directory in force-app/test/ directory and select New Folder.
  2. Enter c for the name of the new directory.
  3. Right-click the c directory and select New File.
  4. Enter displayPanel.html for the name of the new file.
  5. Enter the following code block into the new file:
    <template></template>
  6. Save the file.
  7. Right-click the new c directory and select New File.
  8. Enter displayPanel.js for the name of the new file.
  9. Enter the following code block into the new file:
    import { LightningElement, api } from 'lwc';
      
    export default class ErrorPanel extends LightningElement {
      @api errors;
      @api notes;
      // any other implementation you may want to expose here
    }
    Notice that there is an api decorator for each parameter passed in the component call.
  10. Save the file.
  11. Open jest.config.js and add this line right under the moduleNameMapper: { line:
    '^c/displayPanel$': '<rootDir>/force-app/test/jest-mocks/c/displayPanel',
  12. Save the file and run the test.
  13. The test passes.

Well done! You are now equipped to write tests for all your Lightning Web Components. You also have the power to make these stub implementations as sophisticated or as simple as you need them to be.

Resources