Cypress: Feature request: paste text into textarea

Created on 23 Dec 2017  Â·  16Comments  Â·  Source: cypress-io/cypress

Currently it is only possible to enter text into a textarea by using the type() method. For larger amounts of text this can be quite cumbersome, as each character is inserted separately, even if the delay is reduced, e.g.{delay: 0}.

To speed up this action, it'd be nice if all of the text could be pasted into the textarea in one go, without having to enter the text one character at a time.

Therefore, I'd like to propose a new method called paste() which inserts larger amounts of text in one go.

Thanks in advance for considering this.

duplicate

Most helpful comment

I realize this is closed, but for those mentioning they couldn't get change detection to work with some of the SPA libraries/frameworks, here's what worked for me with Angular:

cy.get('[data-cy=markdown-textarea]').clear().invoke('val', text).trigger('input');

All 16 comments

Can you just put "el.value = text" command?

Sent from my iPhone

On Dec 22, 2017, at 18:04, Kiffin Gish notifications@github.com wrote:

Currently it is only possible to enter text into a textarea by using the type() method. For larger amounts of text this can be quite cumbersome, as each character is inserted separately, even if the delay is reduced, e.g.{delay: 0}.

To speed up this action, it'd be nice if all of the text could be pasted into the textarea in one go, without having to enter the text one character at a time.

Therefore, I'd like to propose a new method called paste() which inserts larger amounts of text in one go.

Thanks in advance for considering this.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.

This is the proposal for what you're asking about: https://github.com/cypress-io/cypress/issues/566

We won't do cy.paste, we'll simply make cy.type type synchronously which would type all the characters in one shot (and make that the default).

Currently as @bahmutov suggests just do cy.get('textarea').invoke('val', myValue').trigger('change')

That's right - with Cypress you have _full and immediate_ access to the DOM so you can do anything you can do from the devtools

Sent from my iPhone

On Dec 22, 2017, at 18:52, Brian Mann notifications@github.com wrote:

This is the proposal for what you're asking about: #566

We won't do cy.paste, we'll simply make cy.type type synchronously which would type all the characters in one shot (and make that the default).

Currently as @bahmutov suggests just do cy.get('textarea').invoke('val', myValue').trigger('change')

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@brian-mann when using your approach I find that the fields in my form get filled but they're not picked up by the Vue.js two-way binding (which does work when using cy.type. Is there an alternative?

@nachocab Same with react-form -> it does not pickup this paste.

That's right - with Cypress you have _full and immediate_ access to the DOM so you can do anything you can do from the devtools

@bahmutov Maybe I'm doing it wrong, but in the console I can do $0.textContent = 'really long text' and I see the text appear in my contenteditable, but when I run it in Cypress it doesn't do anything:

cy.get(`.beam-sequence > .beam--current [contenteditable]`).then($span => {
      $span.textContent = 'really long text';
});

Ah, never mind. I caught my mistake. This works:

cy.get(`.beam-sequence > .beam--current [contenteditable]`).then($span => {
      $span.text('really long text');
});

I realize this is closed, but for those mentioning they couldn't get change detection to work with some of the SPA libraries/frameworks, here's what worked for me with Angular:

cy.get('[data-cy=markdown-textarea]').clear().invoke('val', text).trigger('input');

Thank you @DanWahlin. I have been trying so many things. Yours did it!

Glad that helped!

Should this works fine instead of type({cmd} v)

/**
 * Simulates a paste event.
 *
 * @param pasteOptions Set of options for a simulated paste event.
 * @param pasteOptions.destinationSelector Selector representing the DOM element that the paste event should be dispatched to.
 * @param pasteOptions.pastePayload Simulated data that is on the clipboard.
 * @param pasteOptions.pasteFormat The format of the simulated paste payload. Default value is 'text'.
 */
function paste({ destinationSelector, pastePayload, pasteType = 'text' }) {
    // https://developer.mozilla.org/en-US/docs/Web/API/Element/paste_event
    cy.get(destinationSelector).then($destination => {
        const pasteEvent = Object.assign(new Event('paste', { bubbles: true, cancelable: true }), {
            clipboardData: {
                getData: (type = pasteType) => pastePayload,
            },
        });
        $destination[0].dispatchEvent(pasteEvent);
    });
}

https://gist.github.com/nickytonline/bcdef8ef00211b0faf7c7c0e7777aaf6

Cypress.Commands.add('paste', {
  prevSubject: true,
  element: true
}, ($element, text) => {
  const subString = text.substr(0, text.length - 1);
  const lastChar = text.slice(-1);

  $element.text(subString);
  $element.val(subString);
  cy.get($element.selector).type(lastChar);
});

Thank you @jamiljay , I really like your approach!

BTW at least in my case I had to change the last line to avoid conflicts with multiple candidate elements:

Cypress.Commands.add('paste', {
    prevSubject: true,
    element: true
}, ($element, text) => {

    const subString = text.substr(0, text.length - 1);
    const lastChar = text.slice(-1);

    $element.text(subString);
    $element.val(subString);
    cy.get($element).type(lastChar);
});

This mostly works for me, but the last line type(lastChar) clears the rest of the text and enters only the last character.

I had to click the field first though it might be implementation specific.

Cypress.Commands.add(
  'paste',
  {
    prevSubject: true,
    element: true,
  },
  ($element, text) => {
    const subString = text.substr(0, text.length - 1);
    const lastChar = text.slice(-1);

    cy.get($element)
      .click()
      .then(() => {
        $element.text(subString);
        $element.val(subString);
        cy.get($element).type(lastChar);
      });
  }
);

Splicing substrings was giving me issues since I had "s in my input text. The following sets the text and value of the element to the given text, unmodified. Then cypress types a space followed by a backspace in order to properly trigger events.

/**
 * @param text: text to be pasted in
 */
// https://github.com/cypress-io/cypress/issues/1123#issuecomment-672640129
Cypress.Commands.add(
    "paste",
    {
        prevSubject: true,
        element: true
    },
    ($element, text) => {
        cy.get($element)
            .click()
            .then(() => {
                $element.text(text)
                $element.val(text)
                cy.get($element).type(" {backspace}")
            })
    }
)
Was this page helpful?
0 / 5 - 0 ratings