12

I thought this would be straight-forward, but it turns out to be a complete nightmare. Found no help on google, in the lwc-recipes or documentation.

Here's my issue: I have a LWC that makes multiple asynchronous server calls, two of them use the same getRecord method from lightning/uiRecordApi.

    @wire(getRecord, {recordId : '$opportunityId', fields: [
        OPPORTUNITY_STAGE_FIELD,
        OPPORTUNITY_SYNCED_QUOTE_STATUS_FIELD,
        OPPORTUNITY_CONTACT_ID,
        OPPORTUNITY_SYNCED_QUOTE_LINE_ITEM_COUNT,
        OPPORTUNITY_ACCOUNT_SHIPPING_ADDRESS_COMPLETE,
        OPPORTUNITY_ACCOUNT_BILLING_ADDRESS_COMPLETE
    ]})
    getOpportunity(result) {
        this.opportunity = result;
        this.contactId = getFieldValue(this.opportunity.data, OPPORTUNITY_CONTACT_ID);
    }

    @wire(getRecord, { recordId : '$contactId', fields: [CONTACT_EMAIL_FIELD]})
    contact;

    @wire(checkPermission)
    permission;

My code works: The data provisioned from getRecord is first written to the opportunity and then to the contact variable.

However, it turns out to be untestable. If I write it like this, the contact-data is written to both the opportunity and the contact variable. If I only emit OPPORTUNITY_VALID, both variables have the opportunity data.

test('valid opportunity and valid contact => submit button enabled', async () => {

    const element = createElement('c-create-order-from-opportunity', {
        is: createOrder 
    });

    element.opportunityId = OPPORTUNITY_VALID.id;
    getRecordWireAdapter.emit(OPPORTUNITY_VALID);
    getRecordWireAdapter.emit(CONTACT_VALID);    
    checkPermissionWireAdapter.emit(true);

    document.body.appendChild(element);

    await Promise.resolve();

    let submitButton = element.shadowRoot.querySelector('[data-id="submitButton"]');
    expect(submitButton.disabled).toBe(false);

    let msgBoxes = element.shadowRoot.querySelectorAll('c-message-box');
    expect(msgBoxes.length).toBe(0);

});

I also tried to use Promise.resolve() between .emit() calls, but this did not work either.

Can anybody help me writing solid unit tests for a component that uses multiple independent @wired properties/functions with getRecord calls? My last resort would be to stop using getRecord in both instances and write my own apex method for getting the contact data so I can then mock the apex method.

  • How you have fix this issue, have you used any alternative without using the apex call for one method? – user1343730 Jan 4 at 16:54
5

This is a known gap in the wire service test utility. It's been around for a while, but we haven't forgotten about it. There's currently some non-trivial changes being made to the internals of how the wire service and wire adapters interact. As soon as those internal settle we will solve this testing gap.

The best place to follow along for a fix would be in the @salesforce/wire-service-jest-util github repo. The specific issue filed for this is here: https://github.com/salesforce/wire-service-jest-util/issues/15

  • I have check the issue but didn't see any resolution about the issue. Do you have any alternative way to fix that or any suggestion for the same regarding fix – user1343730 Jan 4 at 16:48
0

Try to use:

  function flushPromises() {
        return new Promise(resolve => setImmediate(resolve));
    }

  test('valid opportunity and valid contact => submit button enabled', async () => {

        const element = createElement('c-create-order-from-opportunity', {
            is: createOrder 
        });

        element.opportunityId = OPPORTUNITY_VALID.id;
        getRecordWireAdapter.emit(OPPORTUNITY_VALID);
        getRecordWireAdapter.emit(CONTACT_VALID);    
        checkPermissionWireAdapter.emit(true);

        document.body.appendChild(element);

        return flushPromises().then(() => {
             let submitButton = element.shadowRoot.querySelector('[data-id="submitButton"]');
             expect(submitButton.disabled).toBe(false);

             let msgBoxes = element.shadowRoot.querySelectorAll('c-message-box');
             expect(msgBoxes.length).toBe(0); 

        });
   });

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.