MeltingDog
MeltingDog

Reputation: 15488

Can I access the results of an assertion or 'it block' and write it to my own report object, in Cypress?

For various reasons I have a custom report object for my Cypress tests.

I alter what the report result is for each step (or it block) using conditonals, eg:

it(`Checks for FAQ schemas`, () => {
        cy.get('script:contains("FAQPage")').its('length').then((len) => {
        if (len > 0) {
            Object.assign(reportObj[testName].steps, {'Page contains no duplicate FAQ Schemas': `${len > 1 ? 'fail' : 'pass'}`});
        }
        else {
            Object.assign(reportObj[testName].steps, {'Page contains no duplicate FAQ Schemas': 'fail - page has FAQs but not FAQ schemas'});
        }
    })
});

Obviously, this is very inefficient and not ideal (not to mention Cypress doesn't even know if the step passes or fails).

I was wondering if there was a way to get the result of an assertion and write that to my reportObj instead, eg something like:

 it(`Checks for FAQ schemas`, () => {
        cy.get('script:contains("FAQPage")').its('length').then((len) => {
           expect(len).to.be.at.least(1);
           // if results of "expect" is true 
           // const result = true
           // else const result = false
           Object.assign(reportObj[testName].steps, {'Page contains no duplicate FAQ Schemas': result})
        })
    });

Does anyone know if I can access the results of an assertion (or it block) from within my test code?

Upvotes: 1

Views: 44

Answers (1)

Aladin Spaz
Aladin Spaz

Reputation: 10018

If you want to report if there are 1 or 2+ elements (corresponding to duplicates: false/true), then you could use assert() instead of expect() and set reportObj value before running the assert.

cy.get('script:contains("FAQPage")').its('length').then((len) => {
  const noDuplicates = (len === 1);  
  const testName = Cypress.currentTest.title
  reportObj[testName] = { 
    steps: {
      'Page contains no duplicate FAQ Schemas': noDuplicates
    }
  }

  assert(noDuplicates, 'There are no duplicates')  
})

If there can be zero FAQPage elements

It becomes a bit trickier if it's possible to have zero elements matching script:contains("FAQPage") because cy.get('script:contains("FAQPage")') fails due to the built-in existence check (i.e when an element is not found the test fails immediately and does not proceed to the .then() check).

One way to tackle it is using events.

Events to access it() block outcome

You can use test:after:run event to update reportObj, and maybe use the fail event to suppress the test failure.

For example, if I visit https://example.com and want to check headings <h1> in the first step and <h2> in the second step, and <p> elements in the third step.

Actually there is one <h1> but no <h2>, and two <p>, so I need to capture all counts for these elements in the reportObj.

describe('reporting on test results using event handlers', () => {

  let count;                // this is set by each step (test)
  let reportObj = {};       // this is the counts for all tests

  // This handles recording the test results
  Cypress.on('test:after:run', (runner, test) => {
    reportObj[test.title] = {
      count
    }
    console.log(reportObj)  // just logging here, or we can save to disk
  })

  Cypress.on('fail', () => {
    // suppress test fail (optional)
  })

  beforeEach(() => {
    count = 0           // initialize to 0 in case the test fails
    cy.visit('https://example.com');
  })

  it('counting elements <h1>', () => {
    cy.get('h1').then($els => count = $els.length)
  })

  it('counting elements <h2>', () => {
    cy.get('h2').then($els => count = $els.length)
  })

  it('counting elements <p>', () => {
    cy.get('p').then($els => count = $els.length)
  })
})

The Cypress.on('test:after:run') event will run if the test passes or fails.

The Cypress.on('fail') event is optional, it will allow the test runner to mark the test as passed (if that is what you need).

This is the Cypress log, you can see the 2nd test has a failed assertion (in red) but the test run continues on to the next step (test).

enter image description here

This is the final reportObj as logged to the console

enter image description here

Upvotes: 1

Related Questions