ã¯ã€ã€ãŒãµãŒãã¹ã® Jest ãã¹ãã®èšè¿°
åŠç¿ã®ç®ç
ãã®åå ãå®äºãããšã次ã®ããšãã§ããããã«ãªããŸãã
- ã¯ã€ã€ãŒãµãŒãã¹ã®äž»ãªã¢ããã¿ãŒã 3 ã€æããã
- ã¯ã€ã€ãŒãµãŒãã¹ã®ããŒã¿ã®ã¢ãã¯ã«ã€ããŠèª¬æããã
- ãªã¢ã¯ãã£ã倿°ãšãã®åœ±é¿ãçè§£ããã
@wire ãµãŒãã¹ã®ãã¹ã
Lightning Web ã³ã³ããŒãã³ãã¯ãLightning ããŒã¿ãµãŒãã¹äžã«æ§ç¯ããããªã¢ã¯ãã£ãã¯ã€ã€ãŒãµãŒãã¹ã䜿çšããŠãSalesforce ããŒã¿ãèªã¿åããŸããã³ã³ããŒãã³ã㯠JavaScript ã¯ã©ã¹ã® @wire ã䜿çšããŠãlightning/ui*Api ã¢ãžã¥ãŒã«ã®ããããã®ã¯ã€ã€ãŒã¢ããã¿ãŒããããŒã¿ãèªã¿åããŸãã
ãã®ã¯ã€ã€ãŒãµãŒãã¹ããªã¢ã¯ãã£ãã§ããçç±ã® 1 ã€ã¯ããªã¢ã¯ãã£ã倿°ããµããŒãããŠããããšã§ãããªã¢ã¯ãã£ã倿°ã«ã¯ $ ã®ãã¬ãã£ãã¯ã¹ãä»ããŠããŸãããªã¢ã¯ãã£ã倿°ã倿Žããããšãã¯ã€ã€ãŒãµãŒãã¹ãæ°ããããŒã¿ãããããžã§ãã³ã°ããŸããããŒã¿ãã¯ã©ã€ã¢ã³ãã®ãã£ãã·ã¥ã«ååšããå Žåã¯ããããã¯ãŒã¯ãªã¯ãšã¹ãã䌎ããªãããšããããŸãã
ããã§ã¯ã@salesforce/sfdx-lwc-jest ãã¹ããŠãŒãã£ãªãã£ã䜿çšããŠããããã®ã³ã³ããŒãã³ããã¯ã€ã€ãŒãµãŒãã¹ããã®ããŒã¿ããšã©ãŒãã©ã®ããã«åŠçãããããã¹ãããŸãã
ãã¹ããããå Žåããã¹ãã§äœ¿çšããå
¥åãå®å
šã«å¶åŸ¡ã§ããããšãæ±ããããŸããå€éšã®ã³ãŒããããŒã¿ãšã®é£åé¢ä¿ã¯èªããããŸãããããã§ã¯ãsfdx-lwc-jest ããããŒã¿ãã¢ãã¯ãããã¹ããŠãŒãã£ãªã㣠API ãã€ã³ããŒãããŠããã¹ãããªã¢ãŒãåŒã³åºãããµãŒããŒé
å»¶ãšãã£ãäºæž¬äžèœãªèŠå ã«å·Šå³ãããªãããã«ããŸãã
ã¯ã€ã€ãŒãµãŒãã¹ã®ããŒã¿ã®ã¢ãã¯ã«äœ¿çšããã¢ããã¿ãŒã«ã¯æ¬¡ã® 3 çš®é¡ããããŸãã
- æ±çšã¯ã€ã€ãŒã¢ããã¿ãŒ: emit() API ãã³ãŒã«ãããšãæ±çšã¢ããã¿ãŒãããŒã¿ããªã³ããã³ãã§çæããŸããããŒã¿èªäœã«é¢ããè¿œå æ
å ±ã¯å«ãŸããŸããã
- Lightning ããŒã¿ãµãŒãã¹ (LDS) ã¯ã€ã€ãŒã¢ããã¿ãŒ: LDS ã¢ããã¿ãŒã¯ Lightning ããŒã¿ãµãŒãã¹ã®åäœãæš¡å£ããŸããããŒã¿ã®ããããã£ã«é¢ããæ
å ±ãå«ãŸããŸãã
- Apex ã¯ã€ã€ãŒã¢ããã¿ãŒ: Apex ã¯ã€ã€ãŒã¢ããã¿ãŒã¯ Apex ã¡ãœãããžã®ã³ãŒã«ãæš¡å£ããŸãããšã©ãŒç¶æ³ãå«ãŸããŸãã
ã§ã¯ãå
žåç㪠@wire ãã³ã¬ãŒã¿ãŒãèŠãŠã¿ãŸããããæå®ããã€ã³ããŒãæ§æã䜿çšããŠãã¯ã€ã€ãŒã¢ããã¿ãŒãã€ã³ããŒãããŸããããããã£ã颿°ã @wire ã§ãã³ã¬ãŒãããŠãã¯ã€ã€ãŒã¢ããã¿ãŒãæå®ããŸããåã¯ã€ã€ãŒã¢ããã¿ãŒãããŒã¿åãå®çŸ©ããŸãã
次ã®ã³ãŒãã¯ãAccount.Name é ç®ãã€ã³ããŒãããŠãã¯ã€ã€ãŒã¢ããã¿ãŒã®èšå®ãªããžã§ã¯ãã§äœ¿çšããŸãã
import { LightningElement, api, wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';
import ACCOUNT_NAME_FIELD from '@salesforce/schema/Account.Name';
export default class Record extends LightningElement {
@api recordId;
@wire(getRecord, { recordId: '$recordId', fields: [ACCOUNT_NAME_FIELD] })
wiredRecord;
}詳ããèŠãŠã¿ãŸãããã
- 8 è¡ç®ã¯
@wireãã³ã¬ãŒã¿ãŒã䜿çšããŠãã€ã³ããŒãæžã¿ã®getRecordã¡ãœããã«ã¢ã¯ã»ã¹ãã$recordIdãªã¢ã¯ãã£ã倿°ã 1 ã€ç®ã®åŒæ°ãšããŠæž¡ããŠããŸãã2 ã€ç®ã®åŒæ°ã¯ã3 è¡ç®ã®ã¹ããŒãããã€ã³ããŒããããAccount.Nameãžã®åç §ã§ãã - 9 è¡ç®ã¯ãã¯ã€ã€ãŒãµãŒãã¹ããããŒã¿ã®ã¹ããªãŒã ãåä¿¡ããéå
¬éã®ããããã£ãŸãã¯é¢æ°ã§ããããããã£ã®å Žåã¯ãçµæããã®ããããã£ã® data ããããã£ãŸã㯠error ããããã£ã«è¿ãããŸãã颿°ã®å Žåã¯ãçµæã data ããããã£ãš error ããããã£ãæå®ãããŠãããªããžã§ã¯ãã§è¿ãããŸãã
ã§ã¯ãåçš®ã®ã¢ããã¿ãŒãèŠãŠãããŸãããã
æ±çšã¯ã€ã€ãŒã¢ããã¿ãŒã®äœ¿çš
æåã«ãCurrentPageReference ãèšå®ãã @wire ãµãŒãã¹ã䜿çšããŸãã
lightning-navigation ãµãŒãã¹ã«ã¯ãURL ãçæããããããŒãžåç
§ã«ç§»åãããããããã®ã¯ã€ã€ãŒã¢ããã¿ãŒã颿°ãçšæãããŠããŸããããã§ã¯ CurrentPageReference ã䜿çšã㊠Salesforce ã®çŸåšã®ããŒãžãžã®åç
§ãååŸãããã®ãã¹ããäœæããŸãã
- Visual Studio Code ã§ã
lwcãã©ã«ããŒãå³ã¯ãªãã¯ãã[SFDX: Create Lightning Web Component (SFDX: Lightning Web ã³ã³ããŒãã³ãã®äœæ)] ãéžæããŸãã - æ°ããã³ã³ããŒãã³ãã®ååã«
ãwireCPRããšå ¥åããŸãã - Enter ããŒãæŒããŸãã
- Enter ããŒãæŒããŠãããã©ã«ãã®
force-app/main/default/lwcãåãå ¥ããŸãã - æ°ãã
wireCPR/__tests__ãã©ã«ããŒã§ãwireCPR.test.jsãã¡ã€ã«ãéããŸãã - æ°ãããã¡ã€ã«ã次ã®ã³ãŒãã§äžæžãããŸãã
import { createElement } from 'lwc'; import WireCPR from 'c/wireCPR'; import { CurrentPageReference } from 'lightning/navigation'; // Mock realistic data const mockCurrentPageReference = require('./data/CurrentPageReference.json'); describe('c-wire-c-p-r', () => { afterEach(() => { while (document.body.firstChild) { document.body.removeChild(document.body.firstChild); } }); it('renders the current page reference in <pre> tag', () => { const element = createElement('c-wire-c-p-r', { is: WireCPR }); document.body.appendChild(element); // Select element for validation const preElement = element.shadowRoot.querySelector('pre'); expect(preElement).not.toBeNull(); // Emit data from @wire CurrentPageReference.emit(mockCurrentPageReference); return Promise.resolve().then(() => { expect(preElement.textContent).toBe( JSON.stringify(mockCurrentPageReference, null, 2) ); }); }); });
- ãã¡ã€ã«ãä¿åããŠããã¹ããå®è¡ããŸãã
詳ããèŠãŠã¿ãŸãããã
- 3 è¡ç®ã¯ã
CurrentPageReferenceã®æ°ããã€ã³ããŒãã§ãã - 5 è¡ç®ã¯ã
PageReferenceãšããã¢ãã¯ããŒã¿ãèšèŒãããã¡ã€ã«ãååŸããŸãããã®ãã¡ã€ã«ã¯ãŸã äœæããŠããªãããããã¹ãã§ãšã©ãŒãçºçãã 1 ã€ç®ã®çç±ã«ãªããŸããåŸã§ãã®ãšã©ãŒãä¿®æ£ããŸããTest suite failed to run Cannot find module './data/CurrentPageReference.json' from 'wireCPR.test.js'
- 21 è¡ç®ã§ã
emit()ã䜿çšããŠã¢ãã¯ããŒã¿ãå ¥åããŸãã - 22 è¡ç®ä»¥éã¯ãã¢ãã¯ããŒã¿ã
preElementã«æŽæ°ãããããšãæ³å®ãã Promise ã§ãã
ã§ã¯ããã¹ãããŒã¿ãã¡ã€ã«ãäœæããŠããã¹ãã«åæ Œããããã³ãŒããæŽæ°ããŸãããããŸãã__tests__ ãã£ã¬ã¯ããªã«ã¢ãã¯ããŒã¿ãã¡ã€ã«ãä¿åãããã£ã¬ã¯ããªãäœæããŸãã
__tests__ãã£ã¬ã¯ããªãå³ã¯ãªãã¯ãã[New Folder (æ°ãããã©ã«ããŒ)] ãéžæããŸãã- æ°ãããã£ã¬ã¯ããªã®ååã«
ãdataããšå ¥åããŸãã - Enter ããŒãæŒããŸãã
dataãã£ã¬ã¯ããªãå³ã¯ãªãã¯ãã[New File (æ°ãããã¡ã€ã«)] ãéžæããŸãããCurrentPageReference.jsonããšå ¥åããŸãã- Enter ããŒãæŒããŸãã
- æ°ãããã¡ã€ã«ã«æ¬¡ã® json ã³ãŒããããã¯ãå
¥åããŸãã
{ "type": "standard__navItemPage", "attributes": { "apiName": "Wire" }, "state": {} }
- ãã¡ã€ã«ãä¿åããŠããã¹ããå®è¡ããŸãã
- ãã¹ãã§æ¬¡ã®ãšã©ãŒã¡ãã»ãŒãžãååŸããŸããã§ããŸãã! ãã¹ãã«å€±æããããšã§ãã³ãŒããé ã«ç¢ºèªããªããåé¡ããã¡æ©ãç¹å®ããŠåŠçãä¿é²ã§ããŸãã
expect(received).not.toBeNull() Received: null
次ã¯ãHTML ã³ãŒããš JavaScript ã³ãŒãã远å ããŸãã
wireCPR.htmlãéããŸãã- 次ã®ã³ãŒãã
templateã¿ã°ã®å åŽã«è¿œå ããŸãã<lightning-card title="Wire CurrentPageReference" icon-name="custom:custom67"> <pre>{currentPageRef}</pre> </lightning-card>
- ãã¡ã€ã«ãä¿åããŸãã
wireCPR.jsãéããŠãã³ãŒããæ¬¡ã®ã³ãŒãã«çœ®æããŸããimport { LightningElement, wire } from 'lwc'; import { CurrentPageReference } from 'lightning/navigation'; export default class WireCPR extends LightningElement { @wire(CurrentPageReference) pageRef; get currentPageRef() { return this.pageRef ? JSON.stringify(this.pageRef, null, 2) : ''; } }
- ãã¡ã€ã«ãä¿åããŠããã¹ããå®è¡ããŸãã
- ãã®ãã¹ãã«åæ ŒããŸãã
äœãè¡ãããã®ãã確èªããŸãããã@wire ã¢ããã¿ãŒã䜿çšãããŠããå ŽåããµãŒãã¹ããè¿ãããæ
å ±ãæ€çŽ¢ãããŸãããã®ããŒã¿ã®ã¢ãã¯ãäœæããå®éã«ãµãŒãã¹ãã³ãŒã«ããŠããŒã¿ãååŸãã代ããã«ã¢ãã¯ã䜿çšããå¿
èŠããããŸããã¢ãã¯ãããã°ãçŸæç¹ã§ååšããé
ç®ã®ã¿ããã¹ããããç¯å²å€ã®äºé
ã¯ãã¹ããããŸããããŸãããã¹ããè¿
éã«å®è¡ãããããã«ãªããŸãã
Lightning ããŒã¿ãµãŒãã¹ã¯ã€ã€ãŒã¢ããã¿ãŒã®äœ¿çš
次ã«ãLightning ããŒã¿ãµãŒãã¹ (LDS) ã« @wire ã䜿çšããŸããLDS ã䜿çšãããšãã«ã¹ã¿ã ãªããžã§ã¯ããæšæºãªããžã§ã¯ãã«ãã°ããã¢ã¯ã»ã¹ã§ããŸããã³ã³ããŒãã³ãã¯ãLDS ã䜿çšã㊠Salesforce ããããŒã¿ãååŸãã衚瀺ããŸããLDS ã¢ããã¿ãŒã䜿çšããŠããŒã¿ãæåŸ
ã©ããã«è¡šç€ºãããããšãæ€èšŒãããã¹ããäœæããŸãã
- Visual Studio Code ã§æ°ãã Lightning Web ã³ã³ããŒãã³ããäœæããŸãã
ãwireLDSããšããååãèšå®ããŸããwireLDS.test.jsãã¹ããã¡ã€ã«ã®ã³ãŒããæ¬¡ã®ã³ãŒãã§äžæžãããŸããimport { createElement } from 'lwc'; import WireLDS from 'c/wireLDS'; import { getRecord } from 'lightning/uiRecordApi'; // Mock realistic data const mockGetRecord = require('./data/getRecord.json'); describe('c-wire-l-d-s', () => { afterEach(() => { while (document.body.firstChild) { document.body.removeChild(document.body.firstChild); } }); describe('getRecord @wire data', () => { it('renders contact details', () => { const element = createElement('c-wire-l-d-s', { is: WireLDS }); document.body.appendChild(element); // Emit data from @wire getRecord.emit(mockGetRecord); return Promise.resolve().then(() => { // Select elements for validation const nameElement = element.shadowRoot.querySelector('p.accountName'); expect(nameElement.textContent).toBe( 'Account Name: ' + mockGetRecord.fields.Name.value ); const industryElement = element.shadowRoot.querySelector('p.accountIndustry'); expect(industryElement.textContent).toBe( 'Industry: ' + mockGetRecord.fields.Industry.value ); const phoneElement = element.shadowRoot.querySelector('p.accountPhone'); expect(phoneElement.textContent).toBe( 'Phone: ' + mockGetRecord.fields.Phone.value ); const ownerElement = element.shadowRoot.querySelector('p.accountOwner'); expect(ownerElement.textContent).toBe( 'Owner: ' + mockGetRecord.fields.Owner.displayValue ); }); }); }); });
- ãã¡ã€ã«ãä¿åããŠããã¹ããå®è¡ããŸãã
- ã¢ãã¯ããŒã¿ããªãããããã¹ãã«å€±æããŸã (ãã®åŸã§ã¢ãã¯ããŒã¿ãäœæããŸã)ã
ãã®åã«ãäœãè¡ãããã®ãããã¹ãã³ãŒãã§ç¢ºèªããŸãããã
- 3 è¡ç®ã¯ã
getRecordã®æ°ããã€ã³ããŒãã§ããgetRecord㯠LDS API ããååŸãããŸãã - 5 è¡ç®ã§åã³
dataãã£ã¬ã¯ããªã®getRecord.jsonãã¡ã€ã«ããããŒã¿ãã¢ãã¯ããŠããŸãã - 19 è¡ç®ã§ã
mockGetRecordãåŒæ°ãšããŠèšå®ããgetRecordã§ emit ã¡ãœããã䜿çšããŸãã - 20 è¡ç®ä»¥éã¯
Promiseæ»ãå€ã§ãããã§ã¯ããŸããŸãªèŠçŽ ãã¢ãã¯ããŒã¿ã䜿çšããŠæŽæ°ãããŠããããšã確èªããŸãã
次ã«ããã¹ãã«åæ Œããããã«ã¢ãã¯ããŒã¿ãã¡ã€ã«ãšæ®ãã®ãã¡ã€ã«ãäœæããŸãããã¡ã€ã«ãäœæãããã³ã«ãã¹ããå®è¡ããåæ ŒãããŸã§ãã¹ããšã©ãŒã®è§£æ¶ç¶æ³ã確èªããŸãã
__tests__ãã£ã¬ã¯ããªã«dataãã£ã¬ã¯ããªãäœæããŸããgetRecord.jsonãšããååã®ãã¹ãããŒã¿ãã¡ã€ã«ãäœæããŸãã- 次ã®ã³ãŒãã远å ããŸãã
{ "apiName" : "Account", "childRelationships" : { }, "eTag" : "35f2effe0a85913b45011ae4e7dae39f", "fields" : { "Industry" : { "displayValue" : "Banking", "value" : "Banking" }, "Name" : { "displayValue" : null, "value" : "Company ABC" }, "Owner" : { "displayValue" : "Test User", "value" : { "apiName" : "User", "childRelationships" : { }, "eTag" : "f1a72efecde2ece9844980f21b4a0c25", "fields" : { "Id" : { "displayValue" : null, "value" : "005o0000000KEEUAA4" }, "Name" : { "displayValue" : null, "value" : "Test User" } }, "id" : "005o0000000KEEUAA4", "lastModifiedById" : "005o0000000KEEUAA4", "lastModifiedDate" : "2019-08-22T23:45:53.000Z", "recordTypeInfo" : null, "systemModstamp" : "2019-08-23T06:00:11.000Z" } }, "OwnerId" : { "displayValue" : null, "value" : "005o0000000KEEUAA4" }, "Phone" : { "displayValue" : null, "value" : "867-5309" } }, "id" : "0011J00001A3VFoQAN", "lastModifiedById" : "005o0000000KEEUAA4", "lastModifiedDate" : "2020-02-28T05:46:17.000Z", "recordTypeInfo" : null, "systemModstamp" : "2020-02-28T05:46:17.000Z" }
- ãã¡ã€ã«ãä¿åããŠããã¹ããå®è¡ããŸãã
- ãã¹ãã«å€±æããŸãã
wireLDS.htmlãéãããã³ãã¬ãŒãã¿ã°ã®å åŽã«æ¬¡ã®ã³ãŒããå ¥åããŸãã<lightning-card title="Wire Lightning Data Service" icon-name="custom:custom108"> <template lwc:if={account.data}> <p class="accountName">Account Name: {name}</p> <p class="accountIndustry">Industry: {industry}</p> <p class="accountPhone">Phone: {phone}</p> <p class="accountOwner">Owner: {owner}</p> </template> <template lwc:if={account.error}> <p>No account found.</p> </template> </lightning-card>
- ãã¡ã€ã«ãä¿åããŠããã¹ããå®è¡ããŸãã
- ä»åããã¹ãã«å€±æããŸãããåæ ŒãŸã§ããšäžæ¯ã§ããããŒã¿ãååŸãã JavaScript ã³ã³ãããŒã©ãŒã远å ããã ãã§ãã
wireLDS.jsãéãããã®ãã¹ãŠã®ã³ãŒããæ¬¡ã®ã³ãŒãã§äžæžãããŸããimport { LightningElement, api, wire } from 'lwc'; import { getRecord, getFieldValue } from 'lightning/uiRecordApi'; import NAME_FIELD from '@salesforce/schema/Account.Name'; import OWNER_NAME_FIELD from '@salesforce/schema/Account.Owner.Name'; import PHONE_FIELD from '@salesforce/schema/Account.Phone'; import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry'; export default class WireLDS extends LightningElement { @api recordId; @wire(getRecord, { recordId: '$recordId', fields: [NAME_FIELD, INDUSTRY_FIELD], optionalFields: [PHONE_FIELD, OWNER_NAME_FIELD] }) account; get name() { return getFieldValue(this.account.data, NAME_FIELD); } get phone() { return getFieldValue(this.account.data, PHONE_FIELD); } get industry(){ return getFieldValue(this.account.data, INDUSTRY_FIELD); } get owner() { return getFieldValue(this.account.data, OWNER_NAME_FIELD); } }
- ãã¡ã€ã«ãä¿åããŠããã¹ããå®è¡ããŸãã
- ãã®ãã¹ãã«åæ ŒããŸãã
ãšããã§ãããŒã¿ã®ååŸäžã«ãšã©ãŒãçºçããå Žåã¯ã©ããªãã®ã§ãããã? ãã®ç¹ããã¹ãã§ããŸããã§ã¯ãwireLDS.test.js ãã¹ããã¡ã€ã«ã«æ°ãã describe ãããã¯ã远å ããŸãããã
- 'getRecord @wire dataâ describe ãããã¯ã®çŽåŸã«æ¬¡ã®ã³ãŒãã远å ããŠã'c-wire-l-d-sâ describe ãããã¯å
ã«é
眮ãããããã«ããŸãããã¹ããæç¢ºã«ããããã«ãdescribe ãããã¯ããã¹ãããããšãã§ããŸãã
describe('getRecord @wire error', () => { it('shows error message', () => { const element = createElement('c-wire-l-d-s', { is: WireLDS }); document.body.appendChild(element); // Emit error from @wire getRecord.error(); return Promise.resolve().then(() => { const errorElement = element.shadowRoot.querySelector('p'); expect(errorElement).not.toBeNull(); expect(errorElement.textContent).toBe('No account found.'); }); }); });
- ãã¡ã€ã«ãä¿åããŠããã¹ããå®è¡ããŸãã
getRecordAdapterã§error()ã¡ãœããã䜿çšããŠããããããã¹ãã«åæ ŒããŸãããã®çµæãã¢ãã¯ããŒã¿ã«ãšã©ãŒãçãããããaccount.errorã true ã«ãªããŸãã
Apex ã¯ã€ã€ãŒã¢ããã¿ãŒã®äœ¿çš
Apex ã®èª¬æã«é²ã¿ã@wire ã䜿çšããŠãã¹ãããã«ã¯ã©ãããã°ãããã確èªããŸãã
LWC ãã€ã³ããŒããã Apex ã¯ã©ã¹ã¯å€éšæ¥ç¶ãšèŠãªããããããã¢ãã¯ããå¿ èŠããããŸããã€ãŸããApex ã¯ã©ã¹ãäœæããªããŠããã¹ãã§ãããšããããšã§ããããã§ãã¹ãããšã¯ãApex ã³ãŒã«ããã®äºæ³ãããå¿çãã¢ãã¯ããã ãã§ãããã®å ŽåãæåŸ ãããã®ã¯ Apex ã¯ã©ã¹ããè¿ãããååŒå ã衚瀺ãããããšã§ããååŒå ãè¿ãããå Žåã«ã¯ãã®ååŒå ã衚瀺ãããè¿ãããªãå Žåã¯ã¡ãã»ãŒãžã衚瀺ãããããšãæåŸ ãããã¹ããäœæããŸãã
ã§ã¯ãApex ã³ãŒã«ã䜿çšãã LWC ãäœæããŸãããã
- Visual Studio Code ã§æ°ãã Lightning Web ã³ã³ããŒãã³ããäœæããŸãã
ãwireApexããšããååãèšå®ããŸããwireApex.test.jsãã¹ããã¡ã€ã«ã®ã³ãŒããæ¬¡ã®ã³ãŒãã§äžæžãããŸããimport { createElement } from 'lwc'; import WireApex from 'c/wireApex'; import getAccountList from '@salesforce/apex/AccountController.getAccountList'; // Realistic data with a list of contacts const mockGetAccountList = require('./data/getAccountList.json'); // An empty list of records to verify the component does something reasonable // when there is no data to display const mockGetAccountListNoRecords = require('./data/getAccountListNoRecords.json'); // Mock getAccountList Apex wire adapter jest.mock( '@salesforce/apex/AccountController.getAccountList', () => { const { createApexTestWireAdapter } = require('@salesforce/sfdx-lwc-jest'); return { default: createApexTestWireAdapter(jest.fn()) }; }, { virtual: true } ); describe('c-wire-apex', () => { afterEach(() => { while (document.body.firstChild) { document.body.removeChild(document.body.firstChild); } // Prevent data saved on mocks from leaking between tests jest.clearAllMocks(); }); describe('getAccountList @wire data', () => { it('renders six records', () => { const element = createElement('c-wire-apex', { is: WireApex }); document.body.appendChild(element); // Emit data from @wire getAccountList.emit(mockGetAccountList); return Promise.resolve().then(() => { // Select elements for validation const accountElements = element.shadowRoot.querySelectorAll('p'); expect(accountElements.length).toBe(mockGetAccountList.length); expect(accountElements[0].textContent).toBe(mockGetAccountList[0].Name); }); }); it('renders no items when no records are returned', () => { const element = createElement('c-wire-apex', { is: WireApex }); document.body.appendChild(element); // Emit data from @wire getAccountList.emit(mockGetAccountListNoRecords); return Promise.resolve().then(() => { // Select elements for validation const accountElements = element.shadowRoot.querySelectorAll('p'); expect(accountElements.length).toBe( mockGetAccountListNoRecords.length ); }); }); }); describe('getAccountList @wire error', () => { it('shows error panel element', () => { const element = createElement('c-wire-apex', { is: WireApex }); document.body.appendChild(element); // Emit error from @wire getAccountList.error(); return Promise.resolve().then(() => { const errorElement = element.shadowRoot.querySelector('p'); expect(errorElement).not.toBeNull(); expect(errorElement.textContent).toBe('No accounts found.'); }); }); }); });
- ãã¡ã€ã«ãä¿åããŠããã¹ããå®è¡ããŸãã
- ã¢ãã¯ããŒã¿ãèŠã€ãããªããšãããšã©ãŒã衚瀺ãããŸãã
ãã®ã³ãŒãã®å€§éšåã¯ä»¥åãšåãã§ãããã®ã¯ãªãŒã³ã¢ããã³ãŒãã«ã¯ããã¹ãã®ååŸã«ã¢ãã¯ããªã»ãããã jest.clearAllMocks() ãšããæ°ããé
ç®ããããŸãã2 çš®é¡ã®ãã¹ãã« 2 ã€ã®ã¢ãã¯ãã¡ã€ã«ãããããããã®é
ç®ãå¿
èŠã«ãªããŸãã1 ã€ç®ã®ãã¹ãã¯ã6 ã€ã®ååŒå
ãæç€ºãã Apex ã³ãŒã«ãæ¢ããŸãã2 ã€ç®ã®ãã¹ãã¯ãååŒå
ãèŠã€ãããªãå Žåã«ã©ããªãããã¢ãµãŒãããŸããæåŸã®ãã¹ãã¯ãApex ã§ãšã©ãŒãçºçããå Žåã«ã©ããªãããã¢ãµãŒãããŸãã
ã§ã¯ãã¢ãã¯ããŒã¿ãã¡ã€ã«ãšæ®ãã®ã³ãŒãã远å ããŸãããã
__tests__ãã£ã¬ã¯ããªã«dataãã£ã¬ã¯ããªãäœæããŸãã- æ°ãã
dataãã£ã¬ã¯ããªã«getAccountList.jsonãšgetAccountListNoRecords.jsonãšããååã® 2 ã€ã®ãã¡ã€ã«ãäœæããŸãã getAccountList.jsonã«æ¬¡ã®ã³ãŒããå ¥åããŸãã[ { "Id": "001o0000005w4fT", "Name": "Edge Communications" }, { "Id": "001o0000005w4fa", "Name": "United Oil & Gas Corporation" }, { "Id": "001o0000005w4fY", "Name": "Express Logistics and Transport" }, { "Id": "001o0000005w4fV", "Name": "Pyramid Construction Inc." }, { "Id": "001o0000005w4fX", "Name": "Grand Hotels & Resorts Ltd" }, { "Id": "001o000000k2NMs", "Name": "ABC Genius Tech Consulting" } ]
getAccountListNoRecords.jsonãã¡ã€ã«ã«æ¬¡ã®ç©ºçœã® JSON ãªããžã§ã¯ããæ¿å ¥ãããŸãã[]
- 次ã«ã
wireApex.htmlã®templateã¿ã°ã®å åŽã«æ¬¡ã®ã³ãŒããå ¥åããŸãã<lightning-card title="Wire Apex" icon-name="custom:custom107"> <template lwc:if={accounts}> <template for:each={accounts} for:item="account"> <p key={account.Id}>{account.Name}</p> </template> </template> <template lwc:if={error}> <p>No accounts found.</p> </template> </lightning-card>
- æåŸã«
wireApex.jsã®ã³ãŒããæ¬¡ã®ã³ãŒãã«çœ®æããŸããããã§ã¯ãimport { LightningElement, wire } from 'lwc'; import getAccountList from '@salesforce/apex/AccountController.getAccountList'; export default class WireApex extends LightningElement { accounts; error; @wire(getAccountList) wiredAccounts({ error, data }) { if(data) { this.accounts = data; this.error = undefined; } else if(error) { this.error = error; this.accounts = undefined; } } }AccountControllerApex ã¯ã©ã¹ããgetAccountListã¡ãœãããååŸããŠããã«éããŸãããLWC ã§ãã®ã¡ãœãããæ©èœãããããã«ã¯ã@AuraEnabled(cacheable=true)ã¢ãããŒã·ã§ã³ãä»å ããå¿ èŠããããŸãã@wireããã®ã¢ãããŒã·ã§ã³ã䜿çšããŠãè¿ãããerrorãŸãã¯dataã颿°ã«å ¥åããŸãã
- ãã¹ãŠã®ãã¡ã€ã«ãä¿åããŠããã¹ããå®è¡ããŸãã
- ãã®ãã¹ãã«åæ ŒããŸãã
次ã®åå ã§ã¯ãä»ã®ã³ã³ããŒãã³ãã®ã¢ãã¯ã«ææŠããJest ã䜿çšã㊠Lightning Web ã³ã³ããŒãã³ãããã¹ãããããããæ¹æ³ãç¿åŸããŸãã
ãªãœãŒã¹
- éçºè ã¬ã€ã: Lightning Web ã³ã³ããŒãã³ã: ã¯ã€ã€ãŒãµãŒãã¹ã䜿çšããããŒã¿ã®ååŸ
- éçºè ã¬ã€ã: Lightning Web ã³ã³ããŒãã³ã: lightning/ui*Api ã¯ã€ã€ãŒã¢ããã¿ãŒãšé¢æ°
- éçºè ã¬ã€ã: ã¯ã€ã€ãŒãµãŒãã¹ã䜿çšãã Lightning Web ã³ã³ããŒãã³ãã® Jest ãã¹ãã®èšè¿°
- User Interface API Developer Guide (ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ API éçºè ã¬ã€ã): Get a Record (ã¬ã³ãŒãã®ååŸ)
- Visual Studio Code åã Salesforce æ¡åŒµæ©èœ: Lightning Web ã³ã³ããŒãã³ã: ãã¹ã
- GitHub: salesforce/wire-service-jest-util
- GitHub: trailheadapps/lwc-recipes
- GitHub: wire-service-jest-util/docs/Migrating from version 2.x to 3.x
