Expect element contains class name puppeteer - puppeteer

so I have an element with a certain id, let's say: #id = test. This element has a class like .form-thumbs-up and I want to obtain an assertion that this element contains 'thumbs-up' in its class but I have no idea how to do it.
I tried
const thumbsUp = await this.page.$('[id="test"]');
const className = await thumbsUp.getProperty('className');
expect(className).toContain('thumbs-up');
but I receive an error like: Expected object: .... to contain value thumbs-up failed.
Do you have any idea how to solve it? Maybe I need to try another approach?
Thanks in advance!

getProperty returns JS handle. You need one more step to get a string:
const className = await (await thumbsUp.getProperty('className')).jsonValue();

Related

Getting the first child element is throwing an error in typescript

I am trying to fetch the first child element of each list item in a typescript file, but typescript always throws error:
Type 'Element' is missing the following properties from type 'HTMLUListElement': compact, type, accessKey, accessKeyLabel, and 109 more. If I neglect this warning and run the HTML file, it works and logs the first first HTML child element, but I need to find a solution to this error to keep a clean code. How can I please remove this error?
const li = document.querySelectorAll('li')
li.forEach((listItem: HTMLLIElement)=> {
listItem.addEventListener('click', (): void => {
err> const *liChild*: HTMLUListElement = listItem.firstElementChild
^ error location
console.log(liChild)
})
})
There's no guarantee that firstElementChild will be a <ul>. It could be any other element, or no element at all (null). So trying to assign this to a HTMLUListElement results in a type error.
If you don't actually care that it's specifically a ul, then either use a type that matches:
listItem.addEventListener("click", (): void => {
const child: Element | null = listItem.firstElementChild;
})
Or leave off the type and typescript will give it that same type automatically
listItem.addEventListener("click", (): void => {
const child = listItem.firstElementChild;
})
If you need to make sure you're dealing with a <ul>, then you'll need to write code to check for that:
listItem.addEventListener("click", (): void => {
const child = listItem.firstElementChild;
if (child && child instanceof HTMLUListElement) {
const ul: HTMLUListElement = child;
console.log(ul);
}
});
Playground link

React-Typescript-useTranslation: Parameter declaration expected. TS1138

I am using React-typescript for my app. For my app, I used useTranslation. useTranslation works fine inside the functional component. I have created validated custom error handler which is outside of the functional component. when I used useTranslation logic, it does work and shows me: Parameter declaration expected. I don't know what I am doing wrong.
const validate = (i: IFormStateValues<IData>, t: any) => {
const errors: IFormStateErrors<IData> = {};
if (!i?.name) {
errors.name = {t(`notValidLengthError`)}; //ERROR:Parameter declaration expected
}
return errors;
};
the easiest way to fix it is by spreading t
const validate = (i: IFormStateValues<IData>, t: any) => {
const errors: IFormStateErrors<IData> = {};
if (!i?.name) {
errors.name = {...t(`notValidLengthError`)}; //ERROR:Parameter declaration expected
}
return errors;
};
but Ad I do not know what t is, I’ll tell you what is happenings, typescript and I have the same question
The property name of errors is been initialed by an Object that does not have any properties I am assuming t is a function that is returning a value, but errors.name is an empty object. There for TS does not like that. setting a value to an empty object with no property where to set the new invomming value.

Can you bind a this value in a generator function

Given that you can't use arrow functions when you need to yield in its body, is it possible to set the this value for use in side the body.
I have made myself a database library which extends the "tedious" library that allows me to do something like the following
const self = this;
db.exec(function*(connection) {
let sql = 'SELECT * FROM myTable WHERE id = #id';
let request = connection.request(sql);
request.addParameter('id',db.TYPE.Int, myIdValue);
let count = yield connection.execSql(function*() {
let row = yield;
while(row) {
//process row with somthing like self.processRow(row);
row=yield;
}
});
if (count > 0) {
request = connection.request('some more sql');
//etc
}
return something;
}).then(something => {
//do some more things if the database access was a success
}).catch(error => {
// deal with any errors.
}) ;
I find I am increasingly needing to access the this value from the outside and am constantly doing the trick of assigning it to self at the head of the surrounding function.
Is it possible to set the this value with something like bind? inside the function* (at multiple levels down!)
Since I have full access to the iterators that I use to implement db.exec and connection.execSql I can change them if it's possible. to support it.
Generator use this as normal functions would.
You have few solutions:
use .bind on generator expression
pass this as first/second argument to generator named self
make db.exec take second argument thisArg, similar to array methods
If a thisArg parameter is provided to forEach(), it will be passed to callback when invoked, for use as its this value. Otherwise, the value undefined will be passed for use as its this value. The this value ultimately observable by callback is determined according to the usual rules for determining the this seen by a function.
I would suggest going with the last solution.

Using ModelCompanion's fromJSON method in Play application throws a NoSuchMethodException

I'm new to Scala and I'm trying to do my first Play 2.0 application. I'm using:
Scala 2.9.3
Play 2.0.4
SalatWithPlay2 1.1
I have this in my conf/routes file:
PUT /newVenue controllers.Application.createNewVenue
I have this in my Application.scala file:
def createNewVenue = Action(parse.json) { request =>
val newVenue = Venue.fromJSON(request.body.toString)
Venue.insert(newVenue)
Ok("New Venue Created")
}
And this is the code for Venue.scala:
import play.api.Play.current
import com.novus.salat._
import com.novus.salat.global._
import com.novus.salat.annotations._
import com.novus.salat.dao._
import com.mongodb.casbah.Imports._
import se.radley.plugin.salat._
object Venue extends ModelCompanion[Venue, ObjectId] {
val collection = mongoCollection("venues")
val dao = new SalatDAO[Venue, ObjectId](collection = collection) {}
}
case class Venue(
#Key("_id") val venueId:ObjectId,
var playlist:Playlist,
var isPlaying:Boolean = false)
To test if this is working I send a PUT request to localhost:9000/newVenue with this JSON as a body:
{"venueId": 3,"playlist":{"playlistId":2,"currentSongPosition":5},"isPlaying":false}
And then I get this error:
[error] application -
! #6d7oco1hf - Internal server error, for request [PUT /newVenue] ->
play.core.ActionInvoker$$anonfun$receive$1$$anon$1: Execution exception [[NoSuchMethodException: model.Venue$.apply$default$1()]]
at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:134) [play_2.9.1.jar:2.0.4]
at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:115) [play_2.9.1.jar:2.0.4]
at akka.actor.Actor$class.apply(Actor.scala:318) [akka-actor.jar:2.0.2]
at play.core.ActionInvoker.apply(Invoker.scala:113) [play_2.9.1.jar:2.0.4]
at akka.actor.ActorCell.invoke(ActorCell.scala:626) [akka-actor.jar:2.0.2]
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:197) [akka-actor.jar:2.0.2]
Caused by: java.lang.NoSuchMethodException: model.Venue$.apply$default$1()
at java.lang.Class.getMethod(Class.java:1605) ~[na:1.6.0_37]
at com.novus.salat.ConcreteGrater.defaultArg(Grater.scala:350) ~[salat-core_2.9.1-1.9.1.jar:1.9.1]
at com.novus.salat.ConcreteGrater.safeDefault(Grater.scala:360) ~[salat-core_2.9.1-1.9.1.jar:1.9.1]
at com.novus.salat.ConcreteGrater$$anonfun$6$$anonfun$apply$7.apply(Grater.scala:319) ~[salat-core_2.9.1-1.9.1.jar:1.9.1]
at com.novus.salat.ConcreteGrater$$anonfun$6$$anonfun$apply$7.apply(Grater.scala:319) ~[salat-core_2.9.1-1.9.1.jar:1.9.1]
at scala.Option.orElse(Option.scala:218) ~[scala-library.jar:0.11.3]
I think the line triggering the error is val newVenue = Venue.fromJSON(request.body.toString).
Does anyone have a clue of what's wrong?
I followed the tutorial in SalatWithPlay2 page and also followed some advices in similar problems), but I had no luck so far.
UPDATE:
I found a workaround, although it's not exactly a solution, but maybe it's helpful for somebody else and for understanding what is the actual solution.
If I remove the annotation #Key, the code of the case class Venue looks like this:
case class Venue(
val venueId:ObjectId,
var playlist:Playlist,
var isPlaying:Boolean = false)
And then I get this other error:
[RuntimeException: in: unexpected OID input class='net.liftweb.json.JsonAST$JInt', value='3']
And if instead of using ObjectId I use Long for example, the code looks like this:
case class Venue(
val venueId:Long,
var playlist:Playlist,
var isPlaying:Boolean = false)
And I get no error!
So the NoSuchMethodException apparently is related to the #Key annotation related to the _id. I also tried to rename venueId to _id and the same NoSuchMethodException error appeared. So the question is: why can't I use the #Key annotation to say which of my attributes maps to the object id of the document in the mongo database?
Besides that, regular Integers cannot be automatically converted to ObjectId instances for some other reason.
Thanks!
Just a shot in the dark, but can you try naming your object class to something else? Maybe to VenueCompanion? It seems it is possible the compiler is getting confused on which object to apply to. IE it is not applying to the case class Venue, that you want. I am curious if the exception is still the same afterwards.
So I found what was the problem.
The attributes of the Json sent in the body of the request must match the names of the attributes of the mongodb's document, not the attributes of the Scala object.
So if my class Venue is defined like this:
case class Venue(
#Key("_id") val venueId:ObjectId,
var playlist:Playlist,
var isPlaying:Boolean = false)
The Json I have to send in the PUT request is:
{"_id": 3,"playlist":{"playlistId":2,"currentSongPosition":5},"isPlaying":false}
And NOT:
{"venueId": 3,"playlist":{"playlistId":2,"currentSongPosition":5},"isPlaying":false}

jqGrid Add Row Data Nested Object

I have a column model like that:
...
{name:'password',index:'password', width:100},
{name:'type.name',index:'type.name', width:100},
...
My class like definitons:
var MyObject = function (password, type) {
this.password = password;
this.type = type;
};
var MyType = function (tname) {
this.tname = tname;
};
I populate my variables: like that:
var type = new MyType($('#typeList').val());
var myObject = new MyObject($('#password').val(), type);
I have a JSON data response from my server and some of it's elements are object as like type. When I want to show them at my grid its OK. However when I want to use addrowdata function I can not see anything at type column. I am doing like that:
$("#gridId").jqGrid('addRowData', myObject.password, myObject, "first");
class is the function that hold name, password etc. inside it. The problem is only with nested elements(I can see password etc. at my grid). addrowData fonction accepts an array but I send a abject that holds object. How can I convert my object of objects into a plaint object array?
Any ideas?
You should not use points in the name property! If needed you can use if in index or in jsonmap.
The usage of addRowData in your example seems me wrong. You should reread the documentation of addRowData method.