Reputation: 15488
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
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')
})
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.
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).
This is the final reportObj
as logged to the console
Upvotes: 1