AssertJ: Asserting that a an array of objects with fields (and values) contains (equals) another array of objects with fields (and values) - assertj

I am trying to figure out if I can write a terser program code than the one I came up with until now.
I start with sharing the code snippet and some explanation after the code snippet:
assertThat(produktUebersichtViews.size()).isEqualTo(4);
assertThat(produktUebersichtViews)
.extracting("objectId", "typ", "title", "status", "bearbeiter", "bearbeiterName",
"erledigungsFrist", "uebersichtTyp", "referencedProduktBasis")
.containsAnyOf(
tuple(ehbEinrichtung.getObjectId(), ehbEinrichtung.getProduktBasisTyp(),
ehbEinrichtung.getName(), ehbEinrichtung.getZustand().name(),
ehbEinrichtung.getBearbeiter(), ehbEinrichtung.getBearbeiterName(),
ehbEinrichtung.getErledigungsFrist(), "PRODUKT_BASIS",
ehbEinrichtung.getReferencedProduktBasis()
)
);
assertThat(produktUebersichtViews)
.extracting("objectId", "typ", "title", "status", "bearbeiter", "bearbeiterName",
"erledigungsFrist", "uebersichtTyp", "referencedProduktBasis")
.containsAnyOf(
tuple(ehbPerson.getObjectId(), ehbPerson.getProduktBasisTyp(), ehbPerson.getName(),
ehbPerson.getZustand().name(), ehbPerson.getBearbeiter(),
ehbPerson.getBearbeiterName(), ehbPerson.getErledigungsFrist(), "PRODUKT_BASIS",
ehbPerson.getReferencedProduktBasis()
)
);
assertThat(produktUebersichtViews)
.extracting("objectId", "typ", "title", "status", "bearbeiter", "bearbeiterName",
"erledigungsFrist", "uebersichtTyp", "referencedProduktBasis")
.containsAnyOf(
tuple(ehbAbrechnung.getObjectId(), ehbAbrechnung.getProduktBasisTyp(),
ehbAbrechnung.getName(), ehbAbrechnung.getZustand().name(),
ehbAbrechnung.getBearbeiter(), ehbAbrechnung.getBearbeiterName(),
ehbAbrechnung.getErledigungsFrist(), "PRODUKT_BASIS",
ehbAbrechnung.getReferencedProduktBasis()
)
);
assertThat(produktUebersichtViews)
.extracting("objectId", "typ", "title", "status", "bearbeiter", "bearbeiterName",
"erledigungsFrist", "uebersichtTyp")
.containsAnyOf(
tuple(pruefbericht.getObjectId(),
pruefbericht.getProduktErgebnisTyp(), pruefbericht.getName(),
pruefbericht.getZustand().name(), pruefbericht.getBearbeiter(),
pruefbericht.getBearbeiterName(), pruefbericht.getErledigungsFrist(),
"PRODUKT_ERGEBNIS"
)
);
The variable produktUebersichtViews is a Set of a type ProduktUebersichtView. This type contains the fields listed in the extracting part.
I wonder if there are better ways (I'm confident there are) to write these assertions more concisely.
The set contains four objects; three of them are the same object type, one is a different type but containing almost all fields.
Ideally I would like to have two assertThat statements; one for the first three cases and one for the last case.
I tried not to clutter too much code in the question. Please let me know if you would like to have more information; I will try to provide.

From my understanding of the problem you could filter by "PRODUKT_BASIS for the first 3 cases and simply write one contains assertion, something like:
assertThat(produktUebersichtViews)
.filteredOn(p -> p.getUebersichtType().equals("PRODUKT_BASIS"))
.extracting("objectId", "typ", "title", "status", "bearbeiter", "bearbeiterName",
"erledigungsFrist", "uebersichtTyp", "referencedProduktBasis")
// not writing the full tuple ...
.contains(tuple(ehbEinrichtung.getObjectId(), ...),
tuple(ehbPerson.getObjectId(), ...),
tuple(ehbAbrechnung.getObjectId(), ...));

Related

Remove the wrapping of json_buid_object in postgresql

This is the query of the postgresql.This returns each object wrapped with json_build_object.How to remove the wrapper of json_build_object and just return it without any wrapper in Postgresql.
let sql = `SELECT json_build_object 'id',Y."Id", 'name',Y."name", 'is_enabled',Y."is_enabled", 'is_setup_complete',Y."is_setup_complete", 'approval_time',Y."approval_time", )
"shops": [
{
"json_build_object": {
"id": 1,
"name": "Melody Garments",
"is_enabled": true,
"is_setup_complete": false,
"approval_time": 10,
"packaging_time": 30,```
Since it looks like your client library is already converting results to JSON, you probably don't need json_build_object at all but instead can use column aliases to control the keys.
SELECT Y."Id" as id, Y."name" as name ...

Sequelize association not returning value

I am trying to understand associations in sequelize and I am able to get one association to work but when I replicate the same query nothing gets returned. I don't understand the relationships that well even after reading the user guide
I can get the data from "stages" but not able to successfully join the "status" table and retrieve the data
I was able to find a workaround too where you can create the association from within findALL()
db.leads
.findAll({
attributes: ["id", "name", "title", "name", "title", "company", "workPhone", "mobilePhone", "otherPhone", "email", "dateCreated"],
include: [
{
model: db.stages,
association: db.leads.hasMany(db.stages, { foreignKey: "id", targetKey: "id" }),
on: {
[Op.and]: [
db.sequelize.where(
db.sequelize.col("stages.id"),
Op.eq, // '=',
db.sequelize.col("leads.stageID")
),
],
},
attributes: ["name"],
},
{
model: db.status,
association: db.leads.belongsToMany(db.status, { through: "id" }),
on: {
[Op.and]: [
db.sequelize.where(
db.sequelize.col("status.id"),
Op.eq, // '=',
db.sequelize.col("leads.statusID")
),
],
},
attributes: ["name"],
},
],
where: {
ownerID: req.query.ownerID,
},
subQuery: false,
duplicating: false,
})
This is what gets returned:
{
"id": "920cc536-48ae-40ee-8c5b-e1bfedbec602",
"name": "Dummy Lead",
"title": "Dummy",
"company": "Dummy",
"workPhone": "000-000-0000",
"mobilePhone": "000-000-0000",
"otherPhone": "000-000-0000",
"email": "Dummy#Dummy.com",
"dateCreated": "2022-06-18T13:30:09.676Z",
"stages": [
{
"name": "Qualify"
}
],
"status_types": []
}
Below are my tables:
Leads:
Stages:
Status:
In general, I believe the recommended approach to associations is to set them up in your models. This will make your queries easier to write, and also help from a DRY perspective. With the associations set up in models, your include would look something like
include: [
{
model: db.stages
attributes: ['name']
}
]
This would LEFT JOIN Stages with Leads. (NB: By adding a property of required: true to the object, you can make that perform an INNER JOIN).
The associations you're trying to call in these queries also do not really seem to match your table structure. If Leads hasMany Stages, then why is there a StageId in the Leads table? Having the foreign key in Leads would suggest that this is a hasOne or belongsTo relation from the Leads side. If Leads SHOULD have many Stages, then the foreign key should exist on the Stages table, so that multiple Stages can be associated to a single Lead.
Defining Leads with a belongsToMany relationship on Status also appears to be incorrect. BelongsToMany is the association method for Many to Many relationships through a junction table. If you do want to have a Many to Many relationship here (Where a Lead can have many Statuses, and Statuses can belong to many Leads), you will need to create that belongsToMany association on each side with a junction table (LeadStatuses). If a Lead should only have one status, however, the association should be lead.belongsTo() and status.hasMany().
I would take a long read about Sequelize Associations to try to take all of this in. It's challenging stuff that you will likely need to revisit several times, but it will make your life much easier once implemented correctly.

How to read JSON with unknown key in ReasonML?

I am writing a simple application that display dog images from Dog API. I used bs-json to make it a record and use it later. The list of breeds can be obtained by the API. The response looks like this.
{
"message": {
"breed": ["array of sub-breeds"],
"breed without subbreed": [],
...
},
"status": "success"
}
So the key is not known at the compile time. If I add it one by one, it would be some kind of hardcode. I only want breeds not sub-breeds. If possible, I would like an array of them.
[| "chihuahua", "golden retreiver", ... |] // Something like this so I can make a select input
I think you could just decode into a Js.Dict.t and then take its keys.
Something like:
let decodeBreeds: Js.Json.t => array(string) =
Json.Decode.(dict(id) |> map(Js.Dict.keys))

Api response structure with configurable columns definitions

I am building an application for a student application system which allows multiple organisations to provide an online application form to its students to apply for courses.
For each application, it will have ID, StudentName, CourseName. However some universities require SecondaryExamMark and some requires Reference name and reference contact no.
I am making an API call (/application/list?pageNo=1&rowsPerPage=20&orgId=1)
and returns all application data with common information plus the extra requirements based on the organisation id provided
I defined an application model that includes all common properties plus a subset of properties all organisations requested and store them in a single database table with a few nullable fields for different organisation.
In terms of the Api response structure, which of the following is more appropriate?
{
ID: 1,
StudentName: 'A B',
CourseName: 'B C',
ReferenceName: null,
ReferenceContact: null,
SecondarySchoolMark: '80'
}
OR
{
headers: [
{
Title: "ID",
Type: "text"
},
{
Title: "StudentName",
Type: "text"
},
{
Title: "CourseName",
Type: "text"
},
{
Title: "SecondarySchoolMark",
Type: "text"
}
],
application: [
{
Title: "ID",
Value: "12345"
},
{
Title: "StudentName",
Value: "A B"
},
{
Title: "CourseName",
Value: 'B C'
}
{
Title: 'SecondarySchoolMark',
Value: '80'
}
]
}
The first approach seems to be a general Api structure which returns an object that describes an application. However the second approach allows the Api to decide which columns should be rendered, and UI would only have to treat the response as display fields.
IMO, i would prefer the first approach because in order to make the API integrate-able with other clients, the API should provide resource based responses. And showing or hiding the columns (whether based on another Api call to /getdisplaycolumns?orgId=1 or just treat null columns as hidden is UI's responsibility)
Edit 1: not necessarily returning the null properties from the approach one as Json serializer allows to ignore null properties)
I agree, settling on a model (resource) that has a couple of nullable properties that the client can ignore sounds like a more robust design (strongly typed properties!) than deserializing whatever the second model is into a Dictionary of sorts and working with that.

CodeMirror: How add tables to sql-hint?

I can't figure how add tables to codemirror. I have sql-hint.js included, and work for keywords but don't understand how add tables and columns...
Sadly, this does not appear to be documented anywhere.
With some trial and error I was able to figure out that you can pass in a structure of table and column names as options when invoking the hinter, like this:
CodeMirror.commands.autocomplete = function(cm) {
CodeMirror.showHint(cm, CodeMirror.hint.sql, {
tables: {
"table1": [ "col_A", "col_B", "col_C" ],
"table2": [ "other_columns1", "other_columns2" ]
}
} );
}
I know that this question is somewhat old but..I found an interesting way, valid in 4.3 release (I don't know anything about older releases): Just add the "CodeMirror.hint.sql" value (without quotes, as its a function) as "hint" option and add the "tables" object as a sub-object defined in "hintOptions" object.
Something like:
CodeMirror.fromTextArea(document.getElementsByTagName("textarea")[0], {
mode: "text/x-sql",
extraKeys: {"Ctrl-Space": "autocomplete"}, // To invoke the auto complete
hint: CodeMirror.hint.sql,
hintOptions: {
tables: {
"table1": [ "col_A", "col_B", "col_C" ],
"table2": [ "other_columns1", "other_columns2" ]
}
}
});
That's it. Note that the "extraKeys" is absolutely not needed, but I found it to be great to test the autocomplete more easily. =)
Good luck. :)