Skip to content

Commit

Permalink
Stephan/order builder test (trailheadapps#212)
Browse files Browse the repository at this point in the history
* update to orderBuilder tests

* update to jest config

* update to the order builder tests

* removal of log statements

* addition of the apex mocks

* Minor fixes

Co-authored-by: pozil <[email protected]>
  • Loading branch information
schandlergarcia and pozil authored Jul 17, 2020
1 parent c7df958 commit 8920836
Show file tree
Hide file tree
Showing 6 changed files with 293 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[
{
"Id": "a003B000004fG1VQAU",
"Qty_S__c": 1,
"Qty_M__c": 1,
"Qty_L__c": 1,
"Price__c": 4200,
"Product__c": "a033B00000381hNQAQ",
"Product__r": {
"Name": "DYNAMO X1",
"MSRP__c": 7000,
"Picture_URL__c": "https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/dynamox1.jpg",
"Id": "a033B00000381hNQAQ",
"$serId$": 343
},
"$serId$": 342
},
{
"Id": "a003B000004fG1aQAE",
"Qty_S__c": 1,
"Qty_M__c": 1,
"Qty_L__c": 1,
"Price__c": 4320,
"Product__c": "a033B00000381hOQAQ",
"Product__r": {
"Name": "DYNAMO X2",
"MSRP__c": 7200,
"Picture_URL__c": "https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/dynamox2.jpg",
"Id": "a033B00000381hOQAQ",
"$serId$": 345
},
"$serId$": 344
},
{
"Id": "a003B000004fG1fQAE",
"Qty_S__c": 1,
"Qty_M__c": 1,
"Qty_L__c": 1,
"Price__c": 4440,
"Product__c": "a033B00000381hPQAQ",
"Product__r": {
"Name": "DYNAMO X3",
"MSRP__c": 7400,
"Picture_URL__c": "https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/dynamox3.jpg",
"Id": "a033B00000381hPQAQ",
"$serId$": 347
},
"$serId$": 346
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
237 changes: 237 additions & 0 deletions force-app/main/default/lwc/orderBuilder/__tests__/orderBuilder.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
import { createElement } from 'lwc';
import OrderBuilder from 'c/orderBuilder';
import { registerApexTestWireAdapter } from '@salesforce/sfdx-lwc-jest';
import getOrderItems from '@salesforce/apex/OrderController.getOrderItems';

// Mock realistic data for the getOrderItems adapter
const mockGetOrderItems = require('./data/getOrderItems.json');
const mockGetOrderItemsEmpty = require('./data/getOrderItemsEmpty.json');

// Mock realistic data for the public properties
const mockRecordId = '0031700000pHcf8AAC';

//Expected Wire Input
const WIRE_INPUT = {
orderId: '0031700000pHcf8AAC'
};

// Register as Apex wire adapter. Some tests verify that provisioned values trigger desired behavior.
const getOrderItemsAdapter = registerApexTestWireAdapter(getOrderItems);

describe('c-order-builder', () => {
afterEach(() => {
// The jsdom instance is shared across test cases in a single file so reset the DOM
while (document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
});

it('displays the correct number of tiles and their details', () => {
// Set values for validating component changes
const expectedItems = 9;
const expectedSum = 38880;

const element = createElement('c-order-builder', {
is: OrderBuilder
});
element.recordId = mockRecordId;
document.body.appendChild(element);

// Emit Data from the Apex wire adapter.s
getOrderItemsAdapter.emit(mockGetOrderItems);

// Return a promise to wait for any asynchronous DOM updates. Jest
// will automatically wait for the Promise chain to complete before
// ending the test and fail the test if the promise rejects.
return Promise.resolve().then(() => {
// Check the wire parameters are correct
expect(getOrderItemsAdapter.getLastConfig()).toEqual(WIRE_INPUT);
// Select elements for validation
const orderItemTileEl = element.shadowRoot.querySelectorAll(
'c-order-item-tile'
);
expect(orderItemTileEl.length).toBe(mockGetOrderItems.length);
// Get the order items to verify they have been set correctly
const { orderItem } = orderItemTileEl[0];
expect(orderItem).toEqual(
expect.objectContaining(mockGetOrderItems[0])
);
// Get the formatted number to verify it has been calculated
const formattedNumberEl = element.shadowRoot.querySelector(
'lightning-formatted-number'
);
expect(formattedNumberEl.value).toBe(expectedSum);
// Get the order total to verify it has been calculated
const orderTotalDivEl = element.shadowRoot.querySelector(
'div.right'
);
expect(orderTotalDivEl.textContent).toBe(
`Total Items: ${expectedItems}`
);
});
});

it('updates the component when an order has been updated', () => {
// Set values for validating component changes
const mockRecordUpdate = { Id: 'a003B000004fG1VQAU', Qty_S__c: 3 };
const expectedItems = 11;
const expectedSum = 47280;

const element = createElement('c-order-builder', {
is: OrderBuilder
});
element.recordId = mockRecordId;
document.body.appendChild(element);

// Emit Data from the Apex wire adapter.s
getOrderItemsAdapter.emit(mockGetOrderItems);

// Return a promise to wait for any asynchronous DOM updates. Jest
// will automatically wait for the Promise chain to complete before
// ending the test and fail the test if the promise rejects.
return Promise.resolve()
.then(() => {
// Check the wire parameters are correct
expect(getOrderItemsAdapter.getLastConfig()).toEqual(
WIRE_INPUT
);
// Select elements for validation
const orderItemTileEl = element.shadowRoot.querySelectorAll(
'c-order-item-tile'
);
orderItemTileEl[0].dispatchEvent(
new CustomEvent('orderitemchange', {
detail: mockRecordUpdate,
bubbles: true
})
);
})
.then(() => {
const orderItemTileEl = element.shadowRoot.querySelectorAll(
'c-order-item-tile'
);
// Get the first order item and check that the quantity has ben updated
const orderItem = orderItemTileEl[0].orderItem.Qty_S__c;
expect(orderItem).toEqual(mockRecordUpdate.Qty_S__c);
// Get the formatted number to verify it has been updated
const formattedNumberEl = element.shadowRoot.querySelector(
'lightning-formatted-number'
);
expect(formattedNumberEl.value).toBe(expectedSum);
// Get the order total to verify it has been updated
const orderTotalDivEl = element.shadowRoot.querySelector(
'div.right'
);
expect(orderTotalDivEl.textContent).toBe(
`Total Items: ${expectedItems}`
);
});
});
it('updates the component when an order has been deleted', () => {
// Set values for validating component changes
const mockRecordToDeleteId = 'a003B000004fG1VQAU';
const expectedItems = 6;
const expectedSum = 26280;

const element = createElement('c-order-builder', {
is: OrderBuilder
});
element.recordId = mockRecordId;
document.body.appendChild(element);

// Emit Data from the Apex wire adapter.
getOrderItemsAdapter.emit(mockGetOrderItems);

// Return a promise to wait for any asynchronous DOM updates. Jest
// will automatically wait for the Promise chain to complete before
// ending the test and fail the test if the promise rejects.
return Promise.resolve()
.then(() => {
// Check the wire parameters are correct
expect(getOrderItemsAdapter.getLastConfig()).toEqual(
WIRE_INPUT
);
// Select elements for validation
const orderItemTileEl = element.shadowRoot.querySelectorAll(
'c-order-item-tile'
);
orderItemTileEl[0].dispatchEvent(
new CustomEvent('orderitemdelete', {
detail: { id: mockRecordToDeleteId }
})
);
})
.then(() => {
const orderItemTileEl = element.shadowRoot.querySelectorAll(
'c-order-item-tile'
);
// Get the first order item and check that the quantity has ben updated
expect(orderItemTileEl.length).toBe(
mockGetOrderItems.length - 1
);
// Get the formatted number to verify it has been updated
const formattedNumberEl = element.shadowRoot.querySelector(
'lightning-formatted-number'
);
expect(formattedNumberEl.value).toBe(expectedSum);
// Get the order total to verify it has been updated
const orderTotalDivEl = element.shadowRoot.querySelector(
'div.right'
);
expect(orderTotalDivEl.textContent).toBe(
`Total Items: ${expectedItems}`
);
});
});

it('displays a panel when no data is returned', () => {
// Set values for validating component changes
const expectedMessage = 'Drag products here to add items to the order';

const element = createElement('c-order-builder', {
is: OrderBuilder
});
element.recordId = mockRecordId;
document.body.appendChild(element);

// Emit Data from the Apex wire adapter.
getOrderItemsAdapter.emit(mockGetOrderItemsEmpty);

// Return a promise to wait for any asynchronous DOM updates. Jest
// will automatically wait for the Promise chain to complete before
// ending the test and fail the test if the promise rejects.
return Promise.resolve().then(() => {
// verify that the placeholder is showing the correct data
const placeholderEl = element.shadowRoot.querySelector(
'c-placeholder'
);
expect(placeholderEl.message).toBe(expectedMessage);
});
});

it('displays a error when an error is returned', () => {
// Set values for validating component changes
const mockError = { message: 'mockError' };

const element = createElement('c-order-builder', {
is: OrderBuilder
});
element.recordId = mockRecordId;
document.body.appendChild(element);

// Emit Data from the Apex wire adapter.
getOrderItemsAdapter.error(mockError);

// Return a promise to wait for any asynchronous DOM updates. Jest
// will automatically wait for the Promise chain to complete before
// ending the test and fail the test if the promise rejects.
return Promise.resolve().then(() => {
// Verify that the error panel is showing the correct data
const errorPanelEl = element.shadowRoot.querySelector(
'c-error-panel'
);
expect(errorPanelEl).not.toBeNull();
expect(errorPanelEl.errors.body).toStrictEqual(mockError);
});
});
});
1 change: 0 additions & 1 deletion force-app/main/default/lwc/orderBuilder/orderBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ export default class OrderBuilder extends LightningElement {
/** Handles drag-and-dropping a new product to create a new Order_Item__c. */
handleDrop(event) {
event.preventDefault();

// Product__c from LDS
const product = JSON.parse(event.dataTransfer.getData('product'));

Expand Down
4 changes: 4 additions & 0 deletions force-app/test/jest-mocks/apex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Mocking how getSObjectValue retrieves the field value.
export const getSObjectValue = (object, field) => {
return object[field.fieldApiName];
};
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { jestConfig } = require('@salesforce/sfdx-lwc-jest/config');
module.exports = {
...jestConfig,
moduleNameMapper: {
'^@salesforce/apex$': '<rootDir>/force-app/test/jest-mocks/apex',
'^lightning/navigation$':
'<rootDir>/force-app/test/jest-mocks/lightning/navigation',
'^lightning/messageService$':
Expand Down

0 comments on commit 8920836

Please sign in to comment.