cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
47.03k stars 3.19k forks source link

type() won't tipe in autoformating field #1684

Closed gcjbr closed 6 years ago

gcjbr commented 6 years ago

I'm testing a client's react app and it has a credit card page. type() is not filling the fields, which are designed to autoformat the input to match a credit card or date format. (4242424242424242 -> 4242 4242 4242 4242).

Is there a way to deal with this behavior or to simply change the field values directly?

kuceb commented 6 years ago

@souljacker could you share the Cypress code you're using with .type ? This should be supported already

gcjbr commented 6 years ago

@Bkucera

 cy.contains('Add card').click();
    cy.contains('Card').click();

    cy.get('input[name=card_number]').its('name');
    cy.get('input[name=card_number]').type('4242424242424242');
    cy.get('input[name=card_number]').its('name');

    cy.get('input[name="card_exp"]').type('0120');
    cy.get('input[name="card_cvc"]').type(123);
    cy.contains('Save card').click();
    cy.contains('xxxx xxxx xxxx 4242');

I know the component is using react-input-mask, but I'm not really sure about how it works

jennifer-shehane commented 6 years ago

This issue is likely related to input masking - this issue also outlines some issues encountered with input masking https://github.com/cypress-io/cypress/issues/940

iam4x commented 6 years ago

Hi :wave:

I ran into the same issue, with react-input-mask and React16 but I have found a workaround.

  it('should format birthdate', () => {
    cy.get('input[id*=birthdate]')
      .as('birthdateInput')
      .then($input => {
        // get native DOM element
        $input = $input.get(0);

        // track last value since we need it for React16 track value
        const lastValue = $input.value;

        $input.value = '29041992';

        // dispatch change into React as well
        $input._valueTracker.setValue(lastValue);
        $input.dispatchEvent(new Event('change', { bubbles: true }));
      });

    cy.get('@birthdateInput').should('have.value', '29/04/1992');
  });

Hope it helps @souljacker 👍

EDIT:

I went a bit further and refactored the piece of code into a Cypress command:

Cypress.Commands.add(
  'typeMask',
  { prevSubject: true },
  (subject, nextValue) => {
    // use native DOM element
    const $input = subject.get(0);

    const lastValue = $input.value;
    $input.value = nextValue;

    // trigger change event
    $input._valueTracker.setValue(lastValue);
    $input.dispatchEvent(new Event('change', { bubbles: true }));

    return subject;
  }
);

You can use it this way:

cy
  .get('input[name*=birthdate]')
  .typeMask('29041992')
  .should('have.value', '29/04/1992')

💯

kuceb commented 6 years ago

I'm looking into this, as well as the other issues in the cy.type() epic #1241

adil-boukdair commented 4 years ago

Clearing the input before typing seems to solve the issue

cy .get('input[name*=birthdate]').clear().typeMask('29041992')

arimourao commented 4 years ago

Can confirm this bug is still alive and well. It fails to fill an masked input text about 50% of the time. This need to be priority.

kuceb commented 4 years ago

@arimourao we have tests around this and they pass. Please present a reproducible example in a new issue if you want an issue looked into. Thanks