cypresscypress-conditional-testing

How to have two different tests for conditional tables that render on a page based upon the prop passed by parent?


I have a cypress test that checks the table on a page, however there are two different tables that could render depending on the table type conditional.

If the type of the table is product one table will render, if the type is equipment a different table will render.

How can I write this cypress test to check IF that specific table is on the page, then run a certain set of checks and vis versa?

Test description:

The conditional is if the selectedIssueKind is Product or Equipment.

The next page will have tables with different column headers and info.

My thought was to have the test check the data-class and then do the tests for that data-class table. So:

if ('[data-cy=product-issue-tracker-table]') { 
  // product table tests
} else {
  // equipment table tests
}

However, if I click on an equipment issue I get an error that it cannot find Part ID, but that's because it's trying to check the wrong table (product).

So my if ('[data-cy=product-issue-tracker-table]') check, doesn't seem to work.

Cypress test

it.only('Issue Tracker table exists, column headers are correct and there is data', () => {
    if ('[data-cy=product-issue-tracker-table]') {
      cy.get('[data-cy=issue-tracker-table] table').contains('th', 'Issue ID')
      cy.get('[data-cy=issue-tracker-table] table').contains('th', 'Part ID')
      cy.get('[data-cy=issue-tracker-table] table').contains(
        'th',
        'Station Name'
      )
      cy.get('[data-cy=issue-tracker-table] table').contains(
        'th',
        'Description'
      )
      cy.get('[data-cy=issue-tracker-table] table').contains('th', 'SN')
      cy.get('[data-cy=issue-tracker-table] table').contains('th', 'Timestamp')
      cy.contains('td', /\w/g).should('be.visible')
    } else {
      cy.get('[data-cy=issue-tracker-table] table').contains('th', 'Issue ID')
      cy.get('[data-cy=issue-tracker-table] table').contains('th', 'Part')
      cy.get('[data-cy=issue-tracker-table] table').contains(
        'th',
        'Station Name'
      )
      cy.get('[data-cy=issue-tracker-table] table').contains(
        'th',
        'Description'
      )
      cy.get('[data-cy=issue-tracker-table] table').contains('th', 'Start Time')
      cy.get('[data-cy=issue-tracker-table] table').contains('th', 'End Time')
      cy.contains('td', /\w/g).should('be.visible')
    }
  })

HTML

<div data-cy="issue-tracker-table">
  <div class="vgt-wrap issue-tracker-table-style cursor-pointer mb-12" data-cy="product-issue-tracker-table" pagination="[object Object]">
    <!--v-if--><div class="vgt-inner-wrap"><!--v-if--><!--v-if--><!--v-if-->
    <div class="vgt-fixed-header"><!--v-if-->
    </div>
    <div class="vgt-responsive">
      <table id="vgt-table" class="vgt-table condensed">
        <colgroup>
          <col id="col-0">
          <col id="col-1">
          <col id="col-2">
          <col id="col-3">
          <col id="col-4">
          <col id="col-5">
          <col id="col-6">
            
       </colgroup>
        <!-- Table header -->
        <thead>
          <tr><!--v-if--><!--v-if-->
            <th scope="col" class="vgt-left-align" aria-sort="descending" aria-controls="col-0" style="min-width: auto; width: auto;">
              <span>Issue ID</span>
              <!--v-if-->
            </th>
            <th scope="col" class="vgt-left-align" aria-sort="descending" aria-controls="col-1" style="min-width: auto; width: auto;">
              <span>Part ID</span>
              <!--v-if-->
            </th>
            <th scope="col" class="vgt-left-align" aria-sort="descending" aria-controls="col-2" style="min-width: auto; width: auto;">
              <span>Station Name</span><!--v-if-->
            </th>
            <th scope="col" class="vgt-left-align" aria-sort="descending" aria-controls="col-3" style="min-width: auto; width: auto;">
              <span>Description</span><!--v-if-->
            </th>
            <th scope="col" class="vgt-left-align" aria-sort="descending" aria-controls="col-4" style="min-width: auto; width: auto;">
              <span>SN</span>
              <!--v-if-->
            </th>
            <th scope="col" class="vgt-left-align" aria-sort="descending" aria-controls="col-5" style="min-width: auto; width: auto;">
              <span>Timestamp</span>
              <!--v-if-->
            </th>
            <th scope="col" class="vgt-left-align" aria-sort="descending" aria-controls="col-6" style="min-width: auto; width: auto;">
              <span></span>
              <!--v-if-->
            </th>
              
            </tr><!--v-if-->
        </thead><!-- Table body starts here -->
        <tbody><!-- if group row header is at the top --><!--v-if--><!-- normal rows here. we loop over all rows -->
          <tr class="">
            <!--v-if--><!--v-if-->
            <td class="vgt-left-align">
              <span>1</span>
                
            </td>
            <td class="vgt-left-align">
              <span></span>
                
            </td>
            <td class="vgt-left-align">
              <span></span>
                
            </td>
            <td class="vgt-left-align">
              <span> Connect to DUT by SSH</span>
                
            </td>
            <td class="vgt-left-align">
              <span></span>
                
            </td>
            <td class="vgt-left-align">
              <span>Mar 28 2022 - 10:01 AM</span>
                
            </td>
            <td class="vgt-left-align"><!--v-if--><!--v-if-->
              <div data-cy="issue-tracker-view-data-button">
                <button class="primary-button">View Data</button>
                  
              </div><!--v-if-->
            </td>
              
            </tr><!-- if group row header is at the bottom --><!--v-if-->
        </tbody><!--v-if-->
      </table>
        
      </div><!--v-if--><!--v-if-->
    </div>
      
    </div><!--v-if--><!-- Issue Data Modals --><!--v-if--><!--v-if--><!-- Issue Data Modals --><!-- Add New Analysis section -->
  <div class="flex">
    <span class="tab font-normal text-card-orange bg-card-orange bg-opacity-20 py-1 px-4 mb-3 mr-9 rounded-full w-max">Analysis Records</span>
    <!--v-if--><!--v-if-->
    <div data-cy="add-new-analysis-button">
      <button class="primary-button">Add New Analysis</button>
        
      </div><!--v-if--></div>
        
 </div>

Solution

  • There's a bit of repetition in the test that may be reduced by getting an array of table headers.

    You may be testing more than headers, but this gives you the idea.

    const headers = ['Issue ID', ...]  // add all the common headers
    
    cy.get('[data-cy="issue-tracker-table"]')
      .then($table => {
        return $table.find('[data-cy=product-issue-tracker-table]').length > 0
      })
      .then(console.log)              // for checking isProduct value
      .then(isProduct => {
        if (isProduct) {
          return headers.concat(['SN', 'Timestamp'])
        } else {
          return headers.concat(['Start Time', 'End Time'])
        }
      })
      .then(console.log)              // for checking headers array
      .then(headers => {
        // One test here
        cy.get('[data-cy=issue-tracker-table] table thead th')
          .each(($th, index, $list)) => {
            // last header is empty, presume you don't want to test it
            if (index < $list.length -1 ) {       
              expect($th.text()).to.eq(headers[index])
            }
          })
      })
    

    Breaking down the steps is useful as well, you can incrementally check each step by (temporarily) logging the result of .then().


    I notice the <!--v-if--> which shows you are using a Vue app.

    If you want to get really sophisticated you can have the app tell Cypress which kind of table is being displayed. This is an app-action and it reduces risks with asynchronous loading.

    The exact code depends on your Vue component, but the pattern is

    // in Vue component
    
    if (window.Cypress) {
      window.tableType = tableType
    }
    
    // in test
    
    cy.window()
      .then(win => {
        return win.tableType === 'Product'
      })
      .then(console.log)              // for checking isProduct value
      .then(isProduct => {
        ...
    

    Testing all <td> has content and visibility

    cy.get('[data-cy=issue-tracker-table] table tbody td')
      .each($td => {
        cy.wrap($td)
          .contains(/\w/)
          .should('be.visible')
      })
    

    Alternative step: tableType instead of isProduct

    cy.get('[data-cy="issue-tracker-table"]')
      .then($table => {
        if ($table.find('[data-cy=product-issue-tracker-table]').length > 0) {
          return 'Product'
        } else {
          return 'Equipment'
        }
      })
      .then(console.log)              // for checking tableType value
      .then(tableType => {
        if (tableType === 'Product') {
          return headers = headers.concat(['SN', 'Timestamp'])
        } else {
          return headers = headers.concat(['Start Time', 'End Time'])
        }
      })
      .then(console.log)              // for checking headers array
      .then(headers => {
        // One test here
        cy.get('[data-cy=issue-tracker-table] table thead th')
          .each(($th, index, $list) => {
            // test header here
            if (index < $list.length -1 ) {
              expect($th.text().trim()).to.eq(headers[index])
            }
          })
      })