Validating that the selected drivers are sent to the server

In this test, we are focused on validating the fact that whatever the user selected from the data table is processed correctly and results in an expected JSON request to the Apex Controller. Of course, the real Apex Controller code is not actually invoked; its mock is!

In this case, the code uses the ability of the Jest framework to record interactions with the mock object it creates and later allows test code to assert that expected parameters were passed. We will also be asserting that toast and custom events got sent by the code. 

As a reminder, here is a shortened version of the Race Setup controller code this test will be testing. For the full version, review the raceSetup.js file in this chapter's sample code:

handleAddDrivers() {
// Construct list of selected drivers
var selectedRows = this.template.querySelector(
'lightning-datatable').getSelectedRows();
var selectedDrivers = [];
selectedRows.forEach(element => {
selectedDrivers.push(element.RecordId);
});
// Call Apex controller methods to add drivers
addDrivers(
{ raceId : this.raceId,
driversToAdd : selectedDrivers })
.then(result => {
// Send toast confirmation to user
this.dispatchEvent(
new ShowToastEvent({
title: 'Add Drivers',
message: 'Add ' + result + ' drivers.',
variant: 'success',
}));
// Send custom event
this.dispatchEvent(
new CustomEvent('added', { detail: result }));
})
.catch(error => {
// Send toast confirmation to user
this.dispatchEvent( ...
});
}

There are two key dependencies in the preceding code that need to be mocked. The first is the lightning-datatable component and return value from the getSelectedRows method. The second is the call to the addDrivers Apex Controller method.

Finally, we want to assert that the events resulting from the dispatchEvent method were fired with the expected arguments. Jest and Salesforce inject mocks for these dependencies for us; all we have to do is configure them and use the expect function to check the results. The following highlights the key steps to this process:

// Step 1: The Apex Controller method is imported to the test code
import addDrivers from
'@salesforce/apex/RaceSetupComponentController.addDriversLwc';

// Step 2: Mock above the Apex Controller method adapter module
jest.mock(
'@salesforce/apex/RaceSetupComponentController.addDriversLwc',
() => {
return {
default: jest.fn()
};
},
{ virtual: true }
);

// Step 3: Setup a mock Apex response the test code expects
addDrivers.mockResolvedValue(MOCK_APEX_RESPONSE);

// Step 4: Setup mocked functions for event listeners
const showToastHandler = jest.fn();
const addedHandler = jest.fn();
element.addEventListener(ShowToastEventName, showToastHandler);
element.addEventListener('added', addedHandler);

// Step 5: Define a mock response for getSelectedRows
tableEl.getSelectedRows = jest.fn().mockReturnValue(SELECTED_ROWS);

Much of the standard Jest API is used in the preceding sample. The jest.mock method shown in step 2 mocks an import statement and is documented at https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options. The jest.fn method is used to create a JavaScript function pointer that records all of the calls made to it for later reference by the test code using the expect method. jest.fn is documented at https://jestjs.io/docs/en/jest-object#jestfnimplementation.

Steps 1 and 2 are executed outside of the specific test code at the top of the test file. Steps 3, 4, and 5, as you can see here, are executed at the appropriate point in the test code itself. As before, the following code uses the Salesforce-provided createElement method to create an instance of the component to test, followed by mock configuration code and code to invoke the handler to simulate the user pressing the Add Drivers button:

// Test: add drivers success
it('add drivers success', () => {

// Given
const MOCK_APEX_RESPONSE = 2;
const RACE_ID = 'a02580000050sJmAAI';
const DRIVER1_ID = 'a015800000AmuwHAAR';
const DRIVER2_ID = 'a015800000AmuwRAAR';
const SELECTED_ROWS =
[
{
"RecordId": DRIVER1_ID,
"Name": "Lewis Hamilton",
"Selected": true
},
{
"RecordId": DRIVER2_ID,
"Name": "Sergio PĂ©rez",
"Selected": true
}
];
const EXPECTED_APEX_PARAMETERS =
{
"raceId" : RACE_ID,
"driversToAdd" : [DRIVER1_ID, DRIVER2_ID]
};
const showToastHandler = jest.fn();
const addedHandler = jest.fn();
const element = createElement('c-raceSetup', {
is: RaceSetup
});
element.raceId = RACE_ID;
element.addEventListener(ShowToastEventName, showToastHandler);
element.addEventListener('added', addedHandler);
addDrivers.mockResolvedValue(MOCK_APEX_RESPONSE);

// Then
document.body.appendChild(element);
const tableEl =
element.shadowRoot.querySelector('lightning-datatable');
tableEl.getSelectedRows =
jest.fn().mockReturnValue(SELECTED_ROWS);

// When
const buttonEl =
element.shadowRoot.querySelectorAll('lightning-button')[1];
buttonEl.click();
return flushPromises().then(() => {
expect(addDrivers.mock.calls[0[0])
.toEqual(EXPECTED_APEX_PARAMETERS);
expect(addedHandler).toHaveBeenCalled();
expect(showToastHandler).toHaveBeenCalled();
expect(showToastHandler.mock.calls[0[0].detail.message)
.toBe('Add ' + MOCK_APEX_RESPONSE + ' drivers.');
});
});

The following are some key aspects of the preceding code to consider:

  • Variables are used to clearly define test data that is used to both build mock responses and, later, to validate the fact that the mocked methods subsequently called received the same values. In other words, the logic correctly passed the inputs and outputs between the test and dependencies, such as the Apex Controller method calls.
  • The standard querySelectorAll method is used to locate the mocked lightning-button component for the Add Drivers button. This is also automatically mocked by the framework, such that when the test code calls the click method, the handleAddDrivers method from the raceSetup.js file is invoked to start the test.
  • The expect method leverages the Jest framework's ability to record interaction with mocked functions. For example, by using .showToastEventHandler.mock.calls, it checks the first invocation and the first parameter of the mock handler associated with the ShowToastEvent sent by the controller code. This confirms that the expected message contains the expected number of drivers. You can read more about the .mocks.calls property here: https://jestjs.io/docs/en/mock-function-api#mockfnmockcalls.
  • The flushPromise method is a boilerplate method defined in the full version of this test, included in the sample code for this chapter. As noted previously, such boilerplate methods are described in more detail in the Salesforce documentation (https://developer.salesforce.com/docs/component-library/documentation/lwc/testing).
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.37.154