testing-library/angular-testing-library

userEvent.type does not work for textarea

apazureck opened this issue · 4 comments

Hi, I have a problem with testing my textarea. I use Angular 15 with Karma / jasmine test runner.

I wanted to test my ace wrapper (ngx-ace-wrapper) NgModel component, but I cannot perform any input with the user event. I replaced the ace component with a simple textarea, but this fails nontheless.

I tried multiple approaches (keyboard, clicking on it, etc.). I cannot see what I am doing wrong here. Maybe you can help me understand the problem.

Thanks!

Here are my currently used versions in my dev dependencies:

"devDependencies": {
    "@angular-devkit/build-angular": "^15.2.4",
    "@angular/cli": "^15.2.4",
    "@angular/compiler-cli": "^15.2.3",
    "@angular/localize": "^15.2.3",
    "@cucumber/cucumber": "^10.0.1",
    "@cucumber/html-formatter": "^20.4.0",
    "@cucumber/messages": "^23.0.0",
    "@cucumber/pretty-formatter": "^1.0.0",
    "@faker-js/faker": "^8.2.0",
    "@playwright/test": "^1.39.0",
    "@testing-library/angular": "^14.3.0",
    "@testing-library/jasmine-dom": "^1.3.3",
    "@testing-library/user-event": "^14.5.1",
    "@types/hammerjs": "^2.0.41",
    "@types/jasmine": "^5.1.1",
    "@types/jasmine-data_driven_tests": "^1.0.6",
    "@types/lodash": "^4.14.191",
    "@types/node": "^18.15.5",
    "@types/omit-deep-lodash": "^1.1.1",
    "@types/testing-library__jasmine-dom": "^1.3.2",
    "@types/tinymce": "^4.6.5",
    "jasmine": "^5.1.0",
    "jasmine-data_driven_tests": "^1.0.0",
    "jasmine-ts-auto-mock": "^2.0.0",
    "karma": "~6.4.1",
    "karma-chrome-launcher": "^3.2.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "^2.1.0",
    "karma-spec-reporter": "^0.0.36",
    "moq.ts": "^10.0.2",
    "ng-mock": "^0.10.10",
    "ng-mocks": "^14.7.1",
    "npm-run-all": "^4.1.5",
    "playwright": "^1.39.0",
    "ts-auto-mock": "3.6.4",
    "ts-node": "^10.9.1",
    "ts-patch": "^3.0.2",
    "typescript": "~4.8.4",
    "uninstall": "^0.0.0"
  },
  "overrides": {
    "jasmine-core": "^5.1.0"
  }

Here is my code:

Template:

<textarea
  [disabled]="disabled"
  data-testid="ace-editor"
  (change)="touched()"
></textarea>

Controller:

import {
  Component,
} from '@angular/core';

@Component({
  selector: 'md-liquid-editor',
  templateUrl: './liquid-editor.component.html',
  styleUrls: ['./liquid-editor.component.scss'],
})
export class LiquidEditorComponent {
}

Spec:

import { LiquidEditorComponent } from './liquid-editor.component';
import {
  render,
  screen,
  waitFor,
} from '@testing-library/angular';
import userEvent from '@testing-library/user-event';

describe('LiquidEditorComponent', () => {
  const renderCut = async () => {
    return await render(LiquidEditorComponent);
  };

  it('should fire value change when value is changed', async () => {
    // Arrange
    const user = userEvent.setup();
    const cut = await renderCut();

    const aceEditor = screen.getByTestId('ace-editor');
    expect(aceEditor).toBeTruthy();

    // Act
    await user.type(aceEditor, 'Hello World{enter}');

    await waitFor(() => {
      throwUnless(screen.getByText('Hello World'));
    });
  });
});

Error message:

TestingLibraryElementError: Unable to find an element with the text: Hello World. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

Ignored nodes: comments, script, style
<body>
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  

  

  

  

  
    
  
    
  
    
  
    
  
  


  <div
    _nghost-a-c101=""
    id="root0"
    ng-version="15.2.4"
  >
    <textarea
      _ngcontent-a-c101=""
      data-testid="ace-editor"
    />
  </div>
</body>

Ignored nodes: comments, script, style
<html>
  <head>
    
    
    <title />
    
    
    <base
      href="/"
    />
    
    
    <meta
      content="text/html; charset=UTF-8"
      http-equiv="Content-Type"
    />
    
    
    <link
      crossorigin="anonymous"
      href="_karma_webpack_/styles.css"
      rel="stylesheet"
    />
    
    
    <meta
      content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
      name="viewport"
    />
    
  
  </head>
  

  
  <body>
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    

    

    

    
    
    
    
    
    
    
    
    
  


    <div
      _nghost-a-c101=""
      id="root0"
      ng-version="15.2.4"
    >
      <textarea
        _ngcontent-a-c101=""
        data-testid="ace-editor"
      />
    </div>
  </body>
</html>...
Error: Unable to find an element with the text: Hello World. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
Ignored nodes: comments, script, style
<body>
  
    
  
    
  
    
  
    
  
    
  
    
  
    
  
  
  
  
  
    
  
    
  
    
  
    
  
  
  <div
    _nghost-a-c101=""
    id="root0"
    ng-version="15.2.4"
  >
    <textarea
      _ngcontent-a-c101=""
      data-testid="ace-editor"
    />
  </div>
</body>
    at waitForWrapper (http://localhost:9976/_karma_webpack_/webpack:/node_modules/@testing-library/dom/dist/@testing-library/dom.esm.js:1121:27)
    at http://localhost:9976/_karma_webpack_/webpack:/node_modules/@testing-library/angular/fesm2022/testing-library-angular.mjs:319:27
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (http://localhost:9976/_karma_webpack_/webpack:/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js:3:1)
    at _next (http://localhost:9976/_karma_webpack_/webpack:/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js:22:1)
    at executor (http://localhost:9976/_karma_webpack_/webpack:/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js:27:1)
    at new ZoneAwarePromise (http://localhost:9976/_karma_webpack_/webpack:/node_modules/zone.js/fesm2015/zone.js:1411:21)
    at http://localhost:9976/_karma_webpack_/webpack:/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js:19:1
    at _waitForWrapper (http://localhost:9976/_karma_webpack_/webpack:/node_modules/@testing-library/angular/fesm2022/testing-library-angular.mjs:326:2)
    at waitForWrapper (http://localhost:9976/_karma_webpack_/webpack:/node_modules/@testing-library/angular/fesm2022/testing-library-angular.mjs:311:30)

Input values don't match queries.
You need to verify the value of the element, for example with:

expect(screen.getByRole('textbox')).toHaveValue('Hello World\n');

Ok, I tried this:

grafik

This does also not work:

grafik

But I still cannot get the value. What am I doing wrong?

Have you tried expect(screen.getByRole('textbox')).toHaveValue('Hello World\n'); ?
Notice the \n at the end, this is because a line break is added due to the {enter}.

Still no luck :( But also in the dom output there is nothig in the textarea element.

grafik

I tried multiple input methods. Not sure if fire event is used correctly, though. Just modified the documentation. I also checked the references and they seem to match (ace editor and textbox in the waitFor.