Saving variables in Cypress - javascript

I want to achieve that my test compares the length of a list. To get the length of my list I`m doing the following :
const oldListCount = cy.get('.grid-row').its('length');
Later in the Test I want to compare the oldListCount with the current length.
newListCount.should('be.gt',oldListCount);
But Cypress says that 'oldListCount' is an [object Object]
I also tried to work with aliases and do an encapsulated .then
like so:
cy.get('.grid-row').its('length').then(newListCount => {
oldLC.then(oldListCount => {
newListCount.should('be.gt', oldListCount.toString());
})
});
But either worked..
Also something worth to mention, when im log both listCounts inside the encapsulated .then the Count is equal, and the UI and the Cypresslogs showing me something else.
For my test it's not important that the Count is a specific number, more important is that the new Count is greater than the old one.
Can somebody please point me in the right direction?

I think something like this will work out
First, you need to save the old list as an alias
cy.get('.grid-row').as('oldList')
and then later in the test
cy.get('#oldList').its('length').then(oldLength => {
cy.get('.grid-row').its('length').should('be.gt' , oldLength)
})

I have solved it by creating the test with a standarized behavior.
So I have no need of saving the count, beacuase I expect always a given response, this should be more Best practice, isn`t it?

Related

Size of jquery.fn.init changes unexpectedly

I'm trying to parse HTML code in jquery, get an attribute of it and extract a number from the id, and then append it to a string like that:
function sortHTMLContentByStrength(x, y) {
console.log($($.parseHTML(x)));
let strength1 =
parseFloat(($("#team-modal-strength-" + $($.parseHTML(x)[1]).attr("id").match(/\d+/)[0]).html()));
let strength2 =
parseFloat(($("#team-modal-strength-" + $($.parseHTML(y)[1]).attr("id").match(/\d+/)[0]).html()));
return strength2 - strength1;
}
The real problem is:
As you can see, i get this S.fn.init(2). Every single console log looks like this. I roughly know what it means and also it wouldn't be a big deal because I used an index to retrieve only the second element (tr tag) which I'm interested in like that:
$($.parseHTML(x)[1])
I'm just getting the second element of the returned array which is tr tag. This code worked and there was nothing wrong with up until now.
So, now the biggest problem. When I run the same code once more later, I don't receive an array of two objects anymore. I get this:
It's not an array anymore so the indexing trick $($.parseHTML(x)[1]) doesn't work anymore.
I really need to call this sorting function multiple times in my program but due to the issue the app breaks. I would be very thankful for any hints on that.

Make AlpineJS recognize changes to objects

I'm using AlpineJS and momentjs. The user can add a bunch of datetimes and those get pushed to an array. This array is rendered to the page with an x-for.
Now I want a method setTime, that changes the time of every datetime object. In theory this is pretty easy. But I figured, that AlpineJS will not catch, that something has changed and therefore not re-render the x-for.
I'm using this.dates.map(item => item.hour(10).minute(0)); in my example here: https://jsfiddle.net/suny1vj9/
Is there a way to tell AlpineJS to rerender, since I know when this needs to be rerendered?
I also thought about having the data twice. One as moment/Date object, and one as the string representation. That solves the problem too, but I feel like there has to be a prettier solution than maintaining two similar arrays and keeping them in sync.
How would you solve this problem differently?
It's a known issue with MomentJS mutability. And since any change in the object replaces the original object, Alpine.js cannot detect the change. To fix it, you will have to clone() the original object after setting the hour and minutes, so that Alpine.js can detect that the object has been changed (I mean it's a new object that time)
Also, the map() function returns the new Array, so you need to change your code like this.
function test() {
return {
dates: [
moment("2022-04-23"),
moment("2022-04-25"),
moment("2022-04-26"),
moment("2022-04-27"),
moment("2022-04-28")],
setTime() {
this.dates = this.dates.map((item) => item.hour(10).minute(0).clone())
},
}
}
This will solve your problem :)
Here is the fiddle link https://jsfiddle.net/tujfyhs2/1/

Cannot put a variable inside channels.get() on discord.js

I've been trying to do some workaround on this thing but it just drives me crazy. The way I see it, it should work just fine but there is something going wrong with it... I hope I am not just really tired and missed a very easy mistake.
Anyway here is the thing. It's something pretty easy to do. an event is activated and then the algorithm below is supposed to read a certain database where I have the ids of the channels I want to send to stored, and it does one loop for each of those ids, outputting a different id on each loop,
(note: I am not doing it inside a client.on("message) event)
let channel = client.channels.get(dbresult)
channel.send(`test`);
This part was supposed to run 2 times with 2 separate numbers on the dbresult variable(since i have just 2 numbers on the database).
Now, when I run this part with just the id number alone and not the dbresult variable like this:
rows.forEach(function(row){
//let dbresult = row.newsid.toString()
let channel = client.channels.get(`0123456789`)
channel.send(`test`);
})
the script works just fine, but when I use the dbresult variable, it gives me this error
channel.send(`test`);
^
TypeError: Cannot read property 'send' of undefined
Now these are the things I've tried:
Putting a console.log(dbresult) just inside the foreach() block. It reads the ids just fine!
Making dbresult a string (as you can see) and also I've tried not converting it into a string too
Just Because I was desperate I even tried this: channel.send(${dbresult}), just in case.
Things that work:
The things I want to get triggered outside this part of the script are just fine, the script always gets activated successfully.
The script always reads each and every one of the ids of the channel. By removing the insides of "foreach" function and putting a console.log(dbresult), I saw that it outputs the different ids I want it to output.
Here is the whole script:
let db = new sqlite.Database('./databases/Serverinfo', sqlite.OPEN_READWRITE | sqlite.OPEN_CREATE);
const sql = 'SELECT newsid FROM news';
db.all(sql, function(error,rows){
if (rows.length <= 0){
return;
}
if (error){
throw error;
}
rows.forEach(function(row){
let dbresult = row.newsid.toString()
console.log(dbresult)
let channel = client.channels.get(dbresult)
channel.send(`test`);
})
db.close();
})
Any help is appriciated of course
If you are using discord.js v.12 you need to use the cache collection.
And yes, the id you want to use needs to be a string.
let channel = client.channels.cache.get(dbresult);
https://discord.js.org/#/docs/main/stable/class/ChannelManager
What you might consider doing is checking if the channel was found before you try to send something.
EDIT: The problem after updating comes from the fact that you store the channelID in your database as an INT which brings the following problem: Numeric literals with absolute values equal to 2^53 or greater are too large to be represented accurately as integers.
What that means is that it doesn't store the ID correctly because it is too large, we are talking in the Quadrillions here. This could happen either at your database or when you import the number into your code. Without knowing your DB setup I can't tell.
Example:
683328323304292410 // the actual ID of the channel
683328323304292400 // the INT that is stored
To fix this you have two options and both need to be implemented in your database.
You can either convert the datatype for the row which stores the channelID to bigINT or convert it when you import the ID source
You can store the channelID as a string in the first place. (probably the easier solution)

JS Slack Notification Filter

Utilizing Slack webhooks and webtask.io I've created a notification filter (based off of a generic script I found online) for Slack that, at this time, filters out messages that contain the string NON-SLA. I'm totally new to JS so getting to this point has all been trial and error. I would like to adjust the script to filter out messages that contain one of any number of strings, but I'm at a roadblock mostly because I'm not familiar with the language and have had 0 luck trying out the various solutions that I've found online.
Here's the current filter for just a single string:
function shouldNotify(data) {
return !data.text.includes('NON-SLA');
}
This returns TRUE for shouldNotify and the rest of the script pushes the message to the specified channel.
I couldn't find a way to do something similar to this:
return !data.text.includes('one','two','three');
Looked into using an array, but nothing of what I found seemed like it would work with the existing script as a whole and I just simply do not have the time to attempt to rewrite it. Seems that this would be the most efficient and proper way to do it though.
Full script can be seen here.
Any help at all would be greatly appreciated as, again, I'm out of ideas with my limited knowledge of this.
TIA
You can use Array.some():
function shouldNotify(data) {
const string = ["one", "two", "three"];
return !string.some(string => data.text.includes(string));
}
// Example:
console.log(shouldNotify({text: "four apples"})); // true
console.log(shouldNotify({text: "two oranges"})); // false
Instead of supplying an arrow function to Array.some, you could alternatively make use of Function.bind and write:
return !string.some(String.includes.bind(string));

Protractor Select Object Which is On Top

I have a test I am trying to create where I change the name of a card. The problem is there is a hidden error card which has the exact same identifiers as what I am trying to edit. The test returns that the object I am trying to work with is unreachable, which makes sense, it is under the one I am working with.
The locator which I have is: textarea[ng-model="ctrl.currentChartTitle"].
Yes, I know that I can do this by model and tried that, but it yields the same results.
Here is a screenshot of the html the yellow is the on top object I am trying to reach:
Not really sure how do to do the selector for this, so it always works.
So I did a bit more searching and found a solution. It looks a like this:
chartTitleTextArea = this.visualizer.all(by.css('textarea[ng-model="ctrl.currentChartTitle"]')).filter((element) => {
return element.isDisplayed().then((isDisplayed) => {
return isDisplayed
})
}).first()
Basically, what this is doing is getting all of the elements which match that locator. Then filtering them on if isDisplayed() is true. Then grabbing the first one.

Categories