components icon indicating copy to clipboard operation
components copied to clipboard

bug(cdk/testing): sendKeys does not update for contenteditable elements

Open ienzam opened this issue 5 years ago • 3 comments

Reproduction

This is a issue with TestHarness, don't know how I can reproduce it with StackBlitz.

Steps to reproduce:

  1. Add a <div contenteditable="true></div>.
  2. Try sendKeys() to that div via harness.

Expected Behavior

The div will show updated text.

Actual Behavior

<div> remains the same.

Environment

  • Angular: master
  • CDK/Material: master
  • Browser(s): akk
  • Operating System (e.g. Windows, macOS, Ubuntu): all

ienzam avatar Apr 18 '20 00:04 ienzam

Is this possibly related to the bug I've been seeing here: https://github.com/angular/components/issues/18984 ? Where typing in a contenteditable div doesn't do anything (and mine just happens to be from the JSONEditor)?

Luminoth avatar Apr 19 '20 22:04 Luminoth

Any news?

skoropadas avatar Aug 26 '20 17:08 skoropadas

Late to the party, but got into this thread while looking for solution to fix unit tests for myself - I will share my workaround.

I see that the typeInElement function (which is used internally when sendKeys method is called) does check if the element is an input or textarea. If so it sets its value property to whatever is passed as parameter to sendKeys. Otherwise it doesn't set any content. Beside that sendKeys dispatch the events: keydown, keypress and keyup.

So the work around is to call sendKeys together with setContenteditableValue. This is how I solve it in my harness:

    private contentEditableDivLocator = this.locatorFor('div[contenteditable="true"');
    
    async getContentEditable(): Promise<TestElement> {
        return await this.contentEditableDivLocator();
    }
    
    
    async typeText(text: string): Promise<void> {
        const contentEditableTestElement = await this.getContentEditable();

        contentEditableTestElement.setContenteditableValue &&
            (await contentEditableTestElement.setContenteditableValue(text));
            
        await contentEditableTestElement.sendKeys(text);
    }

Note:

  1. For some reason setContenteditableValue is possibly undefined, so need to do this ugly check
  2. It is still worth calling sendKeys as it dispatches events. That way we mock real browser behavior the most.

Vastlaan avatar Apr 17 '24 08:04 Vastlaan