Loose equality in Mocha - javascript

In my test, I am passing an object that has two boolean values (among other values) to my API. I am then testing that the object was stored correctly in my database. The response should be exactly the same as the input, except that MySql stores booleans as integers.
I would like to test all of the fields without repetitive code, so I have written this:
const validChannel = {
id: `${new Date().getTime()}`,
major_nbr: 2,
minor_nbr: 1,
delivery: 'ATSC1',
display_nbr: '2.10',
opt_in: true,
visible: true,
callsign: 'TEST',
};
const channel = api.get();
Object.keys(validChannel).forEach((k) => {
expect(channel[k]).to.equal(validChannel[k]);
});
This works great, except that Mocha uses strict comparison, so 1 != true. How can I make this work while still keeping it compact?

Related

Prisma/React Query Dependent undefined type challenges

I would like to take the output of one query (a TRPC query on Prisma) and use this as the dependent input in a future query.
I followed the dependent documentation for React Query but running into type errors that the return of the first may possibly be undefined (e.g. product is possibly 'undefined'):
const { data: product } = api.product.getUnique.useQuery({ id: pid });
const options = api.option.getAll.useQuery(
{
product: product.productSize,
region: product.productRegion,
},
{ enabled: !!product }
);
Does the inclusion of enabled not already handle this? If not, what is the correct way to adapt for Typescript.
Just casting the product value as a boolean return any truthy value (f.e if product will be equal to {} it will still result in true, that means that product won't necessarily have the productSize or productRegion properties, I would change it first to:
{ enabled: !!product && product.productSize && product.productRegion }
If that doesn't fix the typescript error, you as a developer can know for sure that the values are actually there so what you can use the as keyword in typescript to tell it that you know for sure that the type is what you want it to be:
(In this example I assumed that the values are string but you can change it to number or whatever the true value of them are)
const options = api.option.getAll.useQuery(
{
product: product.productSize as string,
region: product.productRegion as string,
},
{ enabled: !!product && product.productSize && product.productRegion }
);

Is there a more accurate way to use <MockedProvider /> for testing apollo requests

I've got my <MockedProvider /> set up passing in mocks={mocks}. everything is working, all good.
the issue is I have a form that whenever any part of it is edited then this makes a mutation, which returns a response and updates the total. say for example, quantity is changed, mutation increases quantity from 1 to 2. total price should double
problem is that in unit tests and mocked provider you only test the functionality in props and hardcoded response. it's not a proper test. perhaps it's more of an e2e/integration test but I was wondering if there's anything you can do with MockedProvider that allows for better testing in this situation?
Instead of using the normal static result property of the objects in the mocks array, you can set a newData function that will run dynamically and use whatever is returned as the result value. For example:
let totalNoteCount = 0;
const mocks = [{
request: {
query: CREATE_NOTE,
variables: {
title: 'Aloha!',
content: 'This is a note ...',
},
},
newData: () => {
// do something dynamic before returning your data ...
totalNoteCount += 1;
return {
data: {
createNote: {
id: 1,
totalNoteCount,
},
},
};
}
}];

Check if a nested property has an object that partially matches a target in expect

I have an object like this:
> const expect = require('chai').expect
> r = { loadedElementData: { userIdRecord: { name: 'Chiara', surname: 'Fabbietti', id: 1 } }, resolvedIdParamsValues: { users: 1 }, resolvedListFilter: {}, totalLoads: 1 }
I can check if an object with specific contents is somewhere deep in r -- this doesn't throw:
> expect(r).to.have.nested.deep.property('loadedElementData.userIdRecord', { name: "Chiara", surname: "Fabbietti", id: 1 })
However, I want to check for partial objects. So, I would like something like this to pass even though the comparison object is a partial match:
> expect(r).to.have.nested.deep.property('loadedElementData.userIdRecord', { id: 1, name: 'Chiara' })
This obviously won't work, since it will check for the object's deep equality.
This in theory should work:
expect(r).to.nested.include({'loadedElementData.userIdRecord': { id: 1, name: 'Chiara' } })
But doesn't.
This should REALLY work:
expect(r).to.deep.nested.include({ 'loadedElementData.userIdRecord': { id: 1, name: 'Chiara' } })
But doesn't.
I can make it work checking ONE property (only 'id'):
expect(r).to.nested.include({ 'loadedElementData.userIdRecord.id': 1})
But I am limited to check for id, and can't check for name too at the same time.
I can do this in 2 steps:
> expect(r).to.include.nested.property('loadedElementData.userIdRecord')
> expect(r.loadedElementData.userIdRecord).to.include({ id: 1 })
But this is a two step process -- can I do it in one step?
If you check their Github issues, maintainers acknowledge that the nested inclusion of an object subset is not working since 2020. Reference: chai Github
This is the line where Chai decides if doing a deep equality or a strict equality when comparing two objects: https://github.com/chaijs/chai/blob/a8359d3d15779a23a7957a4c52539d48de2763e0/lib/chai/core/assertions.js#L1892.
_.eql is a reference to Chai's deep equal own library implementation.
In the deep-eql library the flow will reach to this function that does loose equality comparisons but not partial ones.

Mongoose: value not incrementing through $inc

I have been struggling with this issue for days. For some unknown reason, a specific field ("reviewCounts") is not incrementing no matter what alternative methods I try.
Here is my Schema
let itemSchema = new mongoose.Schema({
rank: Number,
image: String,
name: String,
title: String,
count: Number,
category: String,
ratings: Object,
reviewCounts: Number,
reviews: Array,
tags: Object,
})
and this is the update method:
Item.findOneAndUpdate({name: item,title:title}, {
$inc:{"reviewCounts":1},
$set:averageQuery,
$inc:query
},{strict:false},
function (err, data) {
}
}
$inc works completely find on "query" not it does not increment "reviewCounts". I have tried using $set to manually set the value, but that did not work too. I doubled-checked and confirmed that the field is int32 as intended. What could be the reason behind this issue?
When you build your update statement this way:
{
$inc:{"reviewCounts":1},
$set:averageQuery,
$inc:query
}
you're duplicating the $inc key in your JavaScript object. JavaScript interprets such code as:
{
$set:averageQuery,
$inc:query
}
so simply last usage of particular key "wins" thus you loose the reviewCounts part.
You need to make sure that there's only one $inc and you can use the spread operator to combine your $inc's:
$inc:{ ...query, "reviewCounts":1 }

jest test to match a returned value as a subset of a hash -without calling the function twice?

I want to match the data structure of a function's returned value against a larger structure (i.e. the returned structure "validates" against a more complete hash). I have a working test that uses toHaveProperty but I'd rather not have to define my object structure in my tests for this particular issue.
What I really want is something that will let me test structure (and not values) that is contained within a larger hash and find a away of not calling the function twice:
// ** this would fail if a property value is different **
test('thing returns something matching the structure within types', () => {
expect(thing()).toBeDefined(
expect(types).toMatchObject(thing())
);
});
here's the structure:
var types = {
changeSheet:{
command: ["s", "sheet"],
options: [],
required: [],
sheet_option: true,
},
checkIn:{
command: ["in", "i"],
options: ["-a", "--at"],
required: [],
sheet_option: false,
},
checkOut:{
command: ["out", "o"],
options: ["-a", "--at"],
required: [],
sheet_option: true,
}
};
Here's the function I'm wanting to test:
function thing() {
return {changeSheet: {
command: ["s", "sheet"],
options: [],
required: [],
sheet_option: false,
}};
}
Notice changeSheet.sheet_option is different from the return value vs the 'types' hash. Is there a jest matching mechanism that will check my structure and ignore the values or am I stuck with toHaveProperty()?
You can use Jest's expect matching tools: http://facebook.github.io/jest/docs/en/expect.html#content
expect(thing()).toMatchObject({
changeSheet: {
command: expect.arrayContaining([
expect.any(String),
expect.any(String)
]),
options: expect.any(Array),
required: expect.any(Array),
sheet_option: expect.any(Boolean)
}
});
That said, what you are testing for here is simply structures/typing which might be better accomplished by using a static type checker like TypeScript or Flow.

Categories