popupcypressvuejs3quasar-frameworkeditbox

Quasar2 Vue3 Cypress q-popup-edit


I have the following vue template:

<template>
  <q-item tag="label" v-ripple>
    <q-popup-edit
      v-model="model"
      :cover="false"
      fit
      buttons
      :validate="validate"
      @before-show="modelProxy = model"
    >
      <template v-slot:title>
        <div class="text-mono">
          {{ name }}
        </div>
      </template>
      <q-input
        color="indigo"
        v-model="modelProxy"
        dense
        autofocus
        counter
        :type="dataType ? dataType : 'text'"
        :hint="hint"
        :error="error"
        :error-message="errorMessage"
      />
    </q-popup-edit>
    <q-item-section>
      <q-item-label class="text-mono">{{ name }}</q-item-label>
      <q-item-label v-if="offset && model && model.length > offset" caption
        >...{{
          model.substring(model.length - offset, model.length)
        }}</q-item-label
      >
      <q-item-label v-else caption>{{ model }}</q-item-label>
    </q-item-section>
  </q-item>
</template>

I would like to perform E2E test using Cypress with the following code snippet:

  it('Verify Edit Box from auto-generated page', () => {
    cy.get('[data-test="popup-edit-setting-1"]').contains("Auto Generated Edit box");
    cy.get('[data-test="popup-edit-setting-2"]').contains("Auto Generated Edit box (Number)");
    cy.get('[data-test="popup-edit-setting-1"]').should("be.enabled"); // XXX
    cy.get('[data-test="popup-edit-setting-1"]').focus().click().type("Hello");//.click("SET");
    cy.get('[data-test="popup-edit-setting-1"]').find("label").should('have.value', 'Hello') // XXX
   });

It stumbles on the XXX points. @Fody's solution works but there is one minor issue. I have 2 popup edit box. One with normal string, another with only numeric. There are 2 test cases for the numeric popup editbox. One with invalid normal string entry and another with valid numbers. The problem is that at the end of the test, the numeric popup edit box does NOT return to display mode. It stays popup.

enter image description here


Solution

  • This is the way I would test q-popup-edit. I used a generic example, yours may differ in some details.

    I aimed to test based on what a user sees rather than any internal class or internal properties.

    The user story is:

    // activate popup editor
    const initialText = 'Click me'
    cy.contains('div.cursor-pointer', initialText)    // displayed initial text 
      .should('be.visible')                           // with hand cursor
      .click()
    
    // initial condition
    cy.focused()                                // after click <input> should have focus
      .as('input')                              // save a reference
      .should('have.prop', 'tagName', 'INPUT')  // verify it is the input
    cy.get('@input')
      .invoke('val')
      .should('eq', initialText)                // displayed text is also in the input
    cy.contains('8').should('be.visible')       // character count
    
    // edit action
    cy.get('@input')                           
      .clear()
      .type('test input')
    cy.get('@input')
      .invoke('val')
      .should('eq', 'test input')              // verify input  
    
    cy.contains('10').should('be.visible')     // character count has changed
    
    // back to display mode
    cy.get('body').click()                     // go back to display mode
    
    cy.contains('div.cursor-pointer', 'test input')
      .should('be.visible')
      .and('contain', 'test input')            // verify display element
    cy.contains('10').should('not.exist')      // edit counter has gone
    

    Notes

    To start the edit, you need to identify the display-mode element. It's easiest if you have some unique text in the field, so try to arrange that in the page initial data.

    If no unique text, look for a label or some other selectable element nearby then navigate to it.

    If you add a data-cy attribute to the <q-popup-edit>, it will not exist in the DOM until the component enters edit-mode (so you can't use it in the initial click()).