cypress: variable scope outside the then block. I am facing issue - variables

I have issue with scope outside the then block. Need help of exerts
it("Badges Count", () => {
var totalBadges
cy.get("div:nth-child(4) > span.quick-stat-figure").then($el => {
cy.get("div.profile-quick-stats > div:nth-child(4)").click();
totalBadges = $el.get(0).textContent;
cy.log("Total Badges", totalBadges); // scope is working here
});
cy.log("Badeges", totalBadges) // scope is not working here
});

In cases such as these I like to use aliases.
Simply wrap() your value, whatever it is, and save it with an alias, then get() and use it wherever you need.
Based on your example it should look something like this:
it("Badges Count", () => {
// var totalBadges - you don't need this anymore
cy.get("div:nth-child(4) > span.quick-stat-figure").then($el => {
cy.get("div.profile-quick-stats > div:nth-child(4)").click();
let totalBadges = $el.get(0).textContent;
cy.wrap(totalBadges).as('totalBadges');
// this is now accessible globally via get('#totalBadges')
});
cy.get('#totalBadges').then((myBadges) => {
cy.log("Badeges :"+ myBadges) // should work just fine
}
});
I know it might not look very intuitive, but working with Cypress you will rarely ever need to use variables.
You can check out the Cypress documentation on aliases here.

Related

vue-test-utils | TypeError: s.split is not a function

I try to run a test with vue-test-utils, including a component that has a mixin included, which has a function using split() on a string. The test looks like this:
describe('adminExample.vue Test', () => {
const wrapper = shallowMount(adminExample, {
global: {
mixins: [globalHelpers, authGatewayForElements, storeService],
plugins: [store]
}
})
it('renders component and is named properly', () => {
// check the name of the component
expect(wrapper.vm.$options.name).toMatch('adminExample')
})
})
adminExample.vue doesn't give any error, so I don't include it here, bit it uses a mixin.
The included mixin, called authGatewayForElements, has a function called decryptToken() and simply decrypt a jwt to get some info. The parameter userToken is declared within data of this mixin. The function looks like this:
decryptToken() {
let base64Split = this.userToken.split('.')[1];
let base64 = base64Split.replace(/-/g, '+').replace(/_/g, '/');
let jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload);
},
Running the test giving me the error TypeError: this.userToken.split is not a function . I´m new to testing with vue-test-utils and maybe or definitely missing something that needs to beincluded in the wrapper, as I expected functions like split() don't need to be included additionally.
EDIT: I get this error on multiple functions, like find(), so I'm pretty sure I just do something wrong. Thanks in advance to anybody pointing that out.

Understanding then() in Cypress

I am reading through the documentation in Cypress and I think I have an idea as to what then() does. It works like promises, where a promise returns another promise, but with then(), we are returning a new subject.
If we look at the code example below, we are using then() because we are returning a new variable, which in this case is called target.
Am I understanding this correctly? If not, can someone correct me?
it.only('Marks an incomplete item complete', () => {
//we'll need a route to stub the api call that updates our item
cy.fixture('todos')
.then(todos => {
//target is a single todo, taken from the head of the array. We can use this to define our route
const target = Cypress._.head(todos)
cy.route(
"PUT",
`api/todos/${target.id}`,
//Here we are mergin original item with an object literal
Cypress._.merge(target, {isComplete: true})
)
})
.then is used to receive the results from cy.fixture('todos'). The variable target is not significant in this code.
In your code sample, the variable that is returned from cy.fixture is named todos - the spacing of the code may be throwing you off here? The .then call is attached to the cy.fixture() call
// These 2 code blocks are the same - just different spacing
cy.fixture('todos')
.then(todos => {});
cy.fixture('todos').then(todos => {});
https://docs.cypress.io/api/commands/fixture.html#Usage
cy.fixture('logo.png').then((logo) => {
// load data from logo.png
})
Using .then() allows you to use the yielded subject in a callback function and should be used when you need to manipulate some values or do some actions.
To put it simply, it is used to play around with the yield of the previous command and work around with it in that case. THEN() command is handy and helpful in debugging the yield of the previous command.
const baseURL = "https://jsonplaceholder.typicode.com";
describe("Get Call-Expect+ normal req", () => {
it("GetPostById-Expect", () => {
cy.request(baseURL + "/posts/1").as("GetPostById");
cy.get("#GetPostById").then((response) => {
//response: status
expect(response.status).to.equal(200);
expect(response.status).to.eq(200);
});
});
Refer: https://docs.cypress.io/api/commands/then#Promises

Vue axios delete request not working. How do I fix it?

Im having issues with delete request, my post, get are working fine.
What am I doing wrong?
removeUser(id) {
axios.delete('https://jsonplaceholder.typicode.com/users' + id)
.then(function(response) {
const user = response.data;
this.users.splice(id, user);
});
if response.status === 204, then delete is succeed.
for the client, here is an axios example, notice there is a ' after users
destroy() {
return request.delete('/api/users/' + id)
}
for the server, here is an Laravel example:
if( $article->delete() ) {
return response()->json(null, 204);
} else {
abort(409);
}
I can see only 1 problem on the code you provided.
You're trying to modify the Vue instance $data users object by executing this.users.splice(id, user);. But you're inside the callback function and this no longer represents the Vue instance.
To fix this & make the users object actually modify after the response comes you'll need to do it like this :
removeUser(id) {
let that = this;
axios.delete('https://jsonplaceholder.typicode.com/users' + id)
.then(function(response) {
const user = response.data;
that.users.splice(id, user);
});
Now , I don't have any code from the back-end so I'll just make some assumptions :
The route might not be well defined > if you're using NodeJS then you should check your routes , it should look like this :
router.route('/users:id').delete(async function(req,res,next){ /* ... */ });
You might have a route problem because / is missing before the user value
1 hint : Again , if you're using NodeJS , you could use this inside your .delete route :
res.status(200).json({ errorCode : null , errorMessage : null , users : [] });
To see if you're receiving it on front-end.
I think you do need to append the trailing '/' to the URL, that way the URL is properly formed, such as "https://jsonplaceholder.typicode.com/users/123" (rather than "users123" at the end).
Aside from that, the first parameter to Array.prototype.splice is the position where item removal should begin. The second (optional) parameter, deleteCount, is the number of items to remove. Beyond deleteCount, you can pass a collection of objects which are to be inserted after the start position and after items have been removed.
You just need to find the object in your this.users array and remove it. If you want to use Array.prototype.splice for that, then you can use Array.prototype.findIndex to find the index of the user in the array then remove it:
// Find the index of the item to remove
const indexOfUserToRemove = this.users.findIndex(u => u.id === id);
// Call splice to remove the item
this.users.splice(indexOfUserToRemove, 1);

How to store the value from text box in another variable using Cypress

name="titleEn" data-testid="edit-category-title-en" type="text" placeholder="Enter category title" value="vxfifyem"
Depending on the purpose, there are few ways to do it:
Global scope variable: (BAD PRACTICE)
let myValue;
before(()=> {
cy.get('[data-testid="edit-category-title-en"]').then($el => {
myValue = $el.text();
})
})
it(()=> {
cy.log(myValue) // myValue is now available
})
but, as you can see the callback and the variable call cannot be used in the same scope, otherwise the variable will be null.
In case you need it in a common scope, then you can use the Cypress.Promise utility, so Cypress will not continue until the promise is resolved.
it('', async () => {
const myValue = await new Cypress.Promise((resolve) => {
cy.get('[data-testid="edit-category-title-en"]')
.invoke('text')
.then((txt) => resolve(txt.toString()))
})
})
cy.log(myValue) // myValue is available
Using Cypress Aliases (BEST PRACTICE)
I do recommend to go throw documentation first: Cypress Variables and Aliases
cy.get('[data-testid="edit-category-title-en"]').invoke('text').as('myValue');
then you can call it via: cy.get('#myValue').

If- else statement inside of method vuejs

I got this method
methods: {
insightsSettings () {
import('pages/details/InsightsSettings')
.then(module => {
module.default.props.dashboard.default = 'financial'
this.$modal.open({
component: module.default,
...this.$modalSettings,
parent: this
})
})
}
},
but the code in and after module.default.props.dashboard.default = 'financial' should be put inside an if-else statement to be able to use this code for both .default= 'project' and .default='hr'.
(they all do the same but have a different path leading to this and giving back different info). Does anyone have an idea how to use this? I did try to literally put the code in an if-else statement, but that didn't work
(please keep in mind I'm a newbie at vuejs and could use all the help (; )