Reputation: 1518
Trying to access the alias value on the this () Context, I followed the docs from https://docs.cypress.io/api/commands/as#Fixture
In the .then callback the dataExample parameter is filled OK, but on this.example it is undefined.
describe('cy.as and this', function () {
it('Testing cy.as and this', function () {
cy.fixture('example.json').as('example')
.then(function (dataExample) {
cy.log('ACCESSING this, dataExample', this, dataExample);
});
cy.log(`ACCESSING this.example : ${JSON.stringify(this['example'])}`, this);
});
});
The first log outputs the following: with the dataExample correctly filled, but the contex.example undefined
The second log outside of .then, with this.example also undefined
If I move the cy.fixture line into a beforeEach() it does work. Cold somebody explain this behavior?
describe('alias', () => {
beforeEach(() => {
cy.fixture('example.json').as('example');
});
it('can access all aliases as properties', function () {
expect(this['example']).not.to.eq(undefined); // true
cy.log('THIS', this); // curious => [0]: Context {_runnable: undefined, test: undefined, example: undefined}
cy.log('THIS.example', this['example']); // {name: 'Using fixtures to represent data', email: '[email protected]',
// body: 'Fixtures are a great way to mock data for responses to routes'}
});
});
Upvotes: 1
Views: 464
Reputation: 10560
A helpful way to think of the flow is that there are two passes:
first pass, runs the javascript of the test and executes plain JS but enqueues Cypress commands (and their callbacks)
second pass executes those commands
So when
cy.log(`ACCESSING this.example : ${JSON.stringify(this['example'])}`, this)
is enqueued in the first pass, the parameter this['example']
is evaluated immediately (value is undefined).
It's not storing the parameter expression to be evaluated in the second pass, which is what most people expect.
But you can defer the parameter evaluation by putting it inside another callback.
cy.then(() => {
// this callback code is enqueued
// so the evaluation of "this['example']" is deferred until the queue is running
cy.log(`ACCESSING this.example : ${JSON.stringify(this['example'])}`, this)
})
Gleb Bahmutov has a blog
How to replace the confusing cy.then command with the less confusing cy.later command
Upvotes: 6
Reputation: 1114
Cypress commands are asynchronous. Cypress does not execute a command immediately, it just puts one into a queue to be executed lately. So any command inside a single block of code will not be executed in this block. And the other block of code means any of this:
it
testbefore
/beforeAll
/after
/afterAll
hooksthen
/should
callbackSo if you want to use a value from a cypress command inside the same it
test, you have to use a then
callback in order to give Cypress time to execute the command.
If you use a cypress command in a beforeEach
hook, the command will be executed by the time when it
code starts.
Upvotes: 1