1. 目的
- 忘れた時に見る
- 検索した際に古い書き方がトップの方に出てきて間違えてしまうことがあったのを防ぎたい
2. 参考
- lwc-recipes
https://github.com/trailheadapps/lwc-recipes - Lightning Web Components Developer Guide
https://developer.salesforce.com/docs/platform/lwc/guide
3. メモ
- 検証に使用しているデモリポジトリ
https://github.com/ShigeoTejima/salesforce-1gp-demo
Lightning Web Component - implementation
refreshApexで正常の場合、エラーの場合の挙動を定義する
refreshApex(this.wiredProperty)
.then(() => {
// 正常の場合の挙動を定義する
})
.catch(error => {
// 正常の場合の挙動を定義する
}
);
or
async someFunction() {
try {
await refreshApex(this.wiredProperty);
// 正常の場合の挙動を定義する
} catch (error) {
// 正常の場合の挙動を定義する
}
}
Lightning Web Component - test
基本的な記述
-
flushPromises
を使用して、コンポーネントの反映を行う
__tests_/demo.test.js
describe('c-demo', () => {
afterEach(() => {
while (document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
jest.clearAllMocks();
});
async function flushPromises() {
return Promise.resolve();
}
describe('list of demos', () => {
it('when data exists', async () => {
const element = createElement('c-demo', {
is: Demo
});
document.body.appendChild(element);
// given:
// - モック定義やテストのための事前操作を記述する
const mockGetDemos = [
{ "id": 1, "name": "Foo", "description": "Foo Description" },
{ "id": 2, "name": "Bar" }
];
getDemos.emit(mockGetDemos);
// when:
// - コンポーネントを更新する
await flushPromises();
// then:
// - 確認対象を検証する
const datatableElement = element.shadowRoot.querySelector('lightning-datatable');
expect(datatableElement.data.length).toBe(2);
expect(datatableElement.data).toEqual([
{ "id": 1, "name": "Foo", "description": "Foo Description" },
{ "id": 2, "name": "Bar" }
])
});
}
@wire
されたApexメソッドのテスト
- 以下のような実装があるとする
demo.js
// ~ 省略 ~
import getDemos from '@salesforce/apex/DemoController.getDemos';
export default class Demo_page extends LightningElement {
@wire(getDemos)
demos;
// ~ 省略 ~
- Apexメソッドのモック定義
-
createApexTestWireAdapter
を使用する
-
__tests__/demo.test.js
// ~ 省略 ~
import getDemos from '@salesforce/apex/DemoController.getDemos';
jest.mock(
'@salesforce/apex/DemoController.getDemos',
() => {
const {
createApexTestWireAdapter
} = require('@salesforce/sfdx-lwc-jest');
return {
default: createApexTestWireAdapter(jest.fn())
};
},
{ virtual: true }
);
describe('demos', () => {
// ~ 省略 ~
- Apexメソッドがデータを返す場合
__tests__/demo.test.js
it('when data exists', async () => {
// ~ 省略 ~
const mockGetDemos = [
{ "id": 1, "name": "Foo", "description": "Foo Description" },
{ "id": 2, "name": "Bar" }
];
getDemos.emit(mockGetDemos);
// ~ 省略 ~
}
- Apexメソッドがエラーとなる場合
__tests__/demo.test.js
it('when returned error to get data', async () => {
// ~ 省略 ~
getDemos.error();
// ~ 省略 ~
}
dispatch
されたShowToastEvent
のテスト
- 例として、
wire
されたApexメソッドがエラーの場合に、トーストを表示する
demo.js
@wire(getDemos)
getDemos(value) {
this.demos = value;
const { data, error } = value;
if (error) {
this.dispatchErrorToast();
} else if (data) {
// nop
}
}
dispatchErrorToast() {
this.dispatchEvent(
new ShowToastEvent({
title: 'Error loading Demo',
message: 'fail to fetch records of demo',
variant: 'error'
})
);
}
__tests_/demo.test.js
import { ShowToastEventName } from 'lightning/platformShowToastEvent';
// ~ 省略 ~
describe('c-demo', () => {
// ~ 省略 ~
it('when returned error to get data', async () => {
const element = createElement('c-demo-page', {
is: Demo_page
});
document.body.appendChild(element);
// given:
// - toast eventにモックされたハンドラーを定義する
const toastHandler = jest.fn();
element.addEventListener(ShowToastEventName, toastHandler);
// - wireされたApexメソッドでエラーを発生させる
getDemos.error();
// when:
// - コンポーネントを反映させる
await flushPromises();
// then:
const datatableElement = element.shadowRoot.querySelector('lightning-datatable');
expect(datatableElement).toBe(null);
// - toast eventに定義したモックされたハンドラーに対して検証を行う
expect(toastHandler).toHaveBeenCalled();
expect(toastHandler).toHaveBeenCalledTimes(1);
});
});
-
ShowToastEventName
、ShowToastEvent
のモジュールを作成する
-trailheadapps/lwc-recipes
の以下のソースをそのまま利用した
- https://github.com/trailheadapps/lwc-recipes/blob/main/force-app/test/jest-mocks/lightning/platformShowToastEvent.js
force-app/test/jest-mocks/lightning/platformShowToastEvent.js
/**
* For the original lightning/platformShowToastEvent mock that comes by default with
* @salesforce/sfdx-lwc-jest, see:
* https://github.com/salesforce/sfdx-lwc-jest/blob/master/src/lightning-stubs/platformShowToastEvent/platformShowToastEvent.js
*/
export const ShowToastEventName = 'lightning__showtoast';
export class ShowToastEvent extends CustomEvent {
constructor(toast) {
super(ShowToastEventName, {
composed: true,
cancelable: true,
bubbles: true,
detail: toast
});
}
}
-
jest.config.js
でモジュール定義する-
moduleNameMapper
の箇所で、lightning/platformShowToastEvent
を定義する
-
jest.config.js
const { jestConfig } = require('@salesforce/sfdx-lwc-jest/config');
module.exports = {
...jestConfig,
modulePathIgnorePatterns: ['<rootDir>/.localdevserver'],
moduleNameMapper: {
'^lightning/platformShowToastEvent$': '<rootDir>/force-app/test/jest-mocks/lightning/platformShowToastEvent'
}
};