magnificent-lamp-44201
01/25/2023, 10:26 PMtypescript
describe('Shopping articles in the SWAG Labs store', () => {
let items: object;
beforeEach(() => {
cy.visit('https://www.saucedemo.com/');
cy.loginForm(Cypress.env('valid_user').username, Cypress.env('valid_user').password);
cy.fixture("products").then((product) => {
items = product;
});
});
it('should purchase items from the store', () => {
cy.get('.title').should('have.text', 'Products'); // Checking if I'm in the Products page
// adding the items to the cart
cy.addProductsToCart();
cy.get('#shopping_cart_container').click();
// checking the products I added
cy.get('div[class="inventory_item_name"]')
.then(($item) => {
return (Cypress.$.makeArray($item)).map((el) => el.innerText)
})
.should('deep.equal', items);
cy.get('#checkout').click();
cy.checkoutForm('Eduardo', 'Videgaray', '89000');
cy.get('#finish').click();
cy.get('.complete-header').should('have.text', 'THANK YOU FOR YOUR ORDER')
});
});
I decided to move the logic of checking if the products are already in the cart into a command. I did the following:
typescript
Cypress.Commands.add('validateProductsInCart', () => {
let items: object;
cy.fixture("products").then((product) => {
items = product;
});
cy.get('div[class="inventory_item_name"]').then(($item) => {
return (Cypress.$.makeArray($item)).map((el) => el.innerText)
}).should('deep.equal', items);
cy.get('#checkout').click();
});
but when I used that approach, my items variable came undefined. I put a log inside the fixture, just to see if my data was retrieved, and indeed: the data was retrieved.
I put a log outside the fixture, and the items variable came undefined. I don't know why. The I tried using a cy.wrap() inside the fixture, but I got the same behaviour (undefined).
(cont.)magnificent-lamp-44201
01/25/2023, 10:26 PMtypescript
cy.fixture("products").then((product) => {
cy.wrap(product).as('product');
});
cy.get('div[class="inventory_item_name"]').then(($item) => {
return (Cypress.$.makeArray($item)).map((el) => el.innerText)
}).should('deep.equal', this.product);
Then I followed this approach:
typescript
Cypress.Commands.add('validateProductsInCart', () => {
cy.fixture("products").then((product) => {
cy.get('div[class="inventory_item_name"]').then(($item) => {
return (Cypress.$.makeArray($item)).map((el) => el.innerText)
}).should('deep.equal', product);
});
cy.get('#checkout').click();
});
and worked.
My questions are: Why was my variable undefined if I stored the data in it? Why if I used cy.wrap() the variable behaved like in the first scenario? If the problem is related to scope, why was in my spec file working fine? (because in there I was declaring the variable as global, I used the variable in a beforeEach() hook to save the data from the fixture, and then I used the variable in my test)handsome-cartoon-58565
01/25/2023, 10:35 PMitems inside .should('deep.equal', items) is read before it's assigned inside cy.fixture().then(). And if you are trying to log items after cy.fixture(), then it's also undefined, because .then() is executed in async manner. Try to put more `console.log`s with numeration, so you will know the exact order of execution of each command theregray-kilobyte-89541
01/26/2023, 11:37 AMmagnificent-lamp-44201
01/26/2023, 5:47 PMundefined value is because the data only exists inside the scope where is called. Is there a way to store the data and then use it into a different scope?gray-kilobyte-89541
01/26/2023, 7:33 PMmagnificent-lamp-44201
01/27/2023, 8:52 PMtypescript
describe('Shopping articles in the SWAG Labs store', () => {
let items;
let items: object;
beforeEach(() => {
cy.visit('https://www.saucedemo.com/');
cy.loginForm(Cypress.env('valid_user').username, Cypress.env('valid_user').password);
cy.fixture("products").then((product) => {
items = product;
});
});
it('should purchase items from the store', () => {
cy.get('.title').should('have.text', 'Products'); // Checking if I'm in the Products page
// adding the items to the cart
cy.addProductsToCart();
cy.get('#shopping_cart_container').click();
// checking the products I added
cy.get('div[class="inventory_item_name"]')
.then(($item) => {
return (Cypress.$.makeArray($item)).map((el) => el.innerText)
})
.should('deep.equal', items);
cy.get('#checkout').click();
cy.checkoutForm('Eduardo', 'Videgaray', '89000');
cy.get('#finish').click();
cy.get('.complete-header').should('have.text', 'THANK YOU FOR YOUR ORDER')
});
});magnificent-lamp-44201
01/27/2023, 8:55 PMtypescript
describe('Shopping articles in the SWAG Labs store', () => {
beforeEach(() => {
cy.visit('https://www.saucedemo.com/');
cy.loginForm(Cypress.env('valid_user').username, Cypress.env('valid_user').password);
});
it('should purchase items from the store', () => {
cy.addProductsToCart();
cy.validateProductsInCart();
cy.checkoutForm('Eduardo', 'Videgaray', '89000');
cy.get('#finish').click();
cy.get('.complete-header').should('have.text', 'THANK YOU FOR YOUR ORDER')
});
});
command.-
typescript
Cypress.Commands.add('validateProductsInCart', () => {
cy.fixture("products").then((product) => {
cy.get('div[class="inventory_item_name"]').then(($item) => {
return (Cypress.$.makeArray($item)).map((el) => el.innerText)
}).should('deep.equal', product);
});
cy.get('#checkout').click();
});
the things I attempted to do.-
typescript
// first approach
cy.fixture("products").then((product) => {
cy.wrap(product).as('product');
});
cy.get('div[class="inventory_item_name"]').then(($item) => {
return (Cypress.$.makeArray($item)).map((el) => el.innerText)
}).should('deep.equal', this.product);
// second approach
Cypress.Commands.add('validateProductsInCart', () => {
let items: object;
cy.fixture("products").then((product) => {
items = product;
});
cy.get('div[class="inventory_item_name"]').then(($item) => {
return (Cypress.$.makeArray($item)).map((el) => el.innerText)
}).should('deep.equal', items);
cy.get('#checkout').click();
});gray-kilobyte-89541
01/28/2023, 1:45 PMmagnificent-lamp-44201
02/03/2023, 9:11 PMlate-planet-4481
02/03/2023, 11:23 PM{ type: 'static' } to the .as() command.
2. Use a global variable. (Again, don't do this for your example.) Sometimes I piggyback off the Cypress object, haha. I'm sure there's good reasons not to do this.
3. If you plan on following this pattern a lot in your code, you can come up with custom commands with prevSubject set to true and then come up with nice ways of chaining them. In my own case, I have a cy.newUser() custom command that yields a user object. If I want to get at the email address or the customer ID, I have little custom commands I created for those too. They work like this:
js
cy.newUser().email().then(email => doSomethingWith(email))
// or...
cy.newUser().customerId().then(customerId => doSomethingWith(customerId))magnificent-lamp-44201
02/05/2023, 3:16 AM