Search code examples
jqueryangularangular-materialcypressmat-select

Using serializeArray() method to verify form data on Cypress for Angular App


So I am writing a test to validate the data entered on a form for an Angular app using Cypress and the serializeArray() method. This is my first time using serializeArray() The testing files are not within the web app, but are in their own separate project folder.

This is how the form is set up in Angular:

    <div class="column">
           <mat-card-content>
               <mat-form-field>
                  <div class ="mat-mdc-form-field">
                       <mat-select formcontrolname="Option1">
                        "USA"
                       </mat-select>
                       <mat-select formcontrolname="Option2">
                       "Canada"
                       </mat-select>
                       <mat-select formcontrolname="Option3">
                       "Mexico"
                       </mat-select>
                  </div class ="mat-mdc-form-field">
               </mat-form-field>
           </mat-card-content>
    </div class="column">

This is how I have the assertion written:

cy.get("form")
     .invoke("serializeArray")
     .should("deep.equal", [
     {
         name: "Option1",
         value: "USA"
     },
     {
          name: "Option2",
          value: "Canada"
     },
     {
          name: "Option3",
          value: "Mexico"
     }
]);

When I run the test, it is telling me it is failing with the following message: assertexpected [] to deeply equal [ Array(3) ]

However, when I check console in dev tools it looks like the data went through. enter image description here

Can someone tell me what I am doing wrong? From the looks of it, the test is telling me that the array is empty, but the console is telling me otherwise. At least that's what I think.


Solution

  • jQuery method serializeArray only works with <form> but angular material gives you custom elements which are not supported.

    You can roll your own process

    cy.get('mat-form-field')
      .find('mat-select')
      .then($matSelects => {
        return [...$matSelects].map(matSelect => 
          ({
            name: matSelect.getAttribute('formcontrolname'),
            value: matSelect.innerText.trim().replace(/"/g, '')
          })
        )
      })
      .should("deep.equal", [
        { name: "Option1", value: "USA" },
        { name: "Option2", value: "Canada" },
        { name: "Option3", value: "Mexico" },
      ])
    

    This passes for your sample fragment, but note that serializeArray applies to all these form controls:

    rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
    rsubmittable = /^(?:input|select|textarea|keygen)/i,
    rcheckableType = ( /^(?:checkbox|radio)$/i )
    

    so you might have to extend the code a lot more to handle other mat-* versions.

    Also note there's some funk around the values, so I added .trim().replace(/"/g, '').

    This would not be possible if you used serializeArray, even if the HTML used regular elements (non mat-* versions).