Jest, React testing a component not exist - jestjs

I have this test:
const rendered = render(
<TransactionReason
reason={{ code: defaultReason }}
/>
);
expect(rendered.getByTestId('reasonInput')).toBeNull();
What I'm trying to do is: there is a component that has the testID = 'reasonInput', but this component is not rendered when the reason prop has that value that I'm giving (code: defaultReason). But I get an error because Jest can't find that id, of course, is not rendered. I thought that that would produce a false or null value, that's why I tried with toBeNull or toBeFalsy or something like that.
How could I then test the not existance of that component?

As the reference states, the difference between getByTestId and queryByTestId is that the former throws an error if there is no matching element:
getBy* queries return the first matching node for a query, and throw
an error if no elements match or if more than one match is found (use
getAllBy instead).
queryBy* queries return the first matching node for a query, and
return null if no elements match. This is useful for asserting an
element that is not present. This throws if more than one match is
found (use queryAllBy instead).
It should be:
expect(rendered.queryByTestId('reasonInput')).toBeNull();

Related

Getting children of an element in Puppeteer: element.children.length works but element.children returns undefined

I have this code snippet:
const historicalDataTable = await findElementByClass(
"table",
elementClass,
page
); // This is a custom function I wrote. Works as expected.
const tableBody = await historicalDataTable.$eval(
"tbody",
(el) => el.children.length
);
console.log(tableBody);
This works as expected and returns the correct amount of children. However when I do
const tableBody = await historicalDataTable.$eval(
"tbody",
(el) => el.children
);
And remove the length, it returns undefined. What is going on here?
el.children (Element#children) will yield an HTMLCollection which is not serializable and can't be marshalled from the page's execution context into yours, so evaluate returns undefined instead.
Now, this isn't fully obvious when looking at the elementHandle.$eval docs as the only indication is that the return value is <Promise<Serializable>>, but it becomes clear from the executionContext.evaluate docs:
returns: <Promise<Serializable>> Promise which resolves to the return value of pageFunction
[...]
If the function passed to the executionContext.evaluate returns a non-Serializable value, then executionContext.evaluate resolves to undefined. DevTools Protocol also supports transferring some additional values that are not serializable by JSON: -0, NaN, Infinity, -Infinity, and bigint literals.
(Emphasis mine.)
el.children.length (HTMLCollection#length) on the other hand is a simple number which is serializable.
You have to do whatever you want to do with those elements inside of your pageFunction and return only some serializable value.
Alternatively, you could also use elementHandle.evaluateHandle to return a JSHandle to the HTMLCollection and use that handle later in another call to an evaluate-type function. (Note that that would be the only thing you can do with it though. You couldn't access .length for example from your own execution context, only from another pageFunction1.)
1: This is not entirely true, since you could for example use jsHandle.getProperty to get another JSHandle for the length, followed by jsHandle.jsonValue to get the value as number - but both of these operations are asynchronous and probably it's a lot more efficient to write your code in such a way that you can handle all the necessary operations inside the page's execution context in the first place, without too many context switches.

"Cannot read property 'map' of undefined" react and node.js

https://github.com/dongha1992/MERN-boilerplate
enter image description here
hello. currently I tried to practice shopping mall clone as react and node.js
I faced that problem I attached. it doesn't seem that error for cos I copied same as tutorial but it is something wrong with node.js(localhost:5000)
I tried to everything to fix it but don't know how to approach. please help me!
enter image description here
Probably an asynchronous request that populates your props.images hasn't returned a response.
Prefix props.images && to props.images.map function
That way only when the prop is present does the the map occur. Like this
{props.images && props.image.map(image=>.........
Ok, this is often an issue of a variable taking on different value during code execution. To safeguard again this, it's recommended to make sure that the props or a specific variable is defined before it's used.
// alternative-1
function ImageSlider(props){
return props.images && (
<div>
<Carousel autoplay>
{props.images.map((image, index) =>
// ...
)}
// ...
</div>
);
};
OR
// alternative-2
function ImageSlider(props){
return props.images ? (
<div>
<Carousel autoplay>
{props.images.map((image, index) =>
// ...
)}
// ...
</div>
) : null;
};
Critically, here's what is happening in the return() statement.
Alternative-1 (Implicit):
The second part, <div> is only rendered if the first part is true.
In core JavaScript, undefined is equivalent to false so props.images is true only when images is !undefined (not undefined; in other words, images is defined).
Alternative-2 (Explicit):
This one is more direct, as long as props.image is undefined, we return null.(Remember, a valid react component must return something. If nothing, then return null)
Only when props.images is defined, then we return the <div>.
These added checks ensure that your code never breaks, in this case your map() will always be called on a defined variable (props.images).
Here's a good read on Conditional rendering from the react team.
It looks like you're trying to call the map function on data that hasn't been received from your axios request. You should add some logic so that any components that rely on your request data render only if it exits, easily done with a ternary operator.
It looks like many components (including imageSlider) depend on data you try to access when you call your renderCards function on line 54 of your App.

Firebase Cloud Function - Reference.update failed

I'm getting the following error when invoking a GCF:
Error: Reference.update failed: First argument path specified exceeds the maximum depth that can be written (32) or object contains a cycle in property
Done a bit of digging online but can't find the same issue. Without adding way too much info, I'm trying to add dish objects into a category object in Realtime Database. The odd thing is, the function works fine for the first 6 dishes, and when I try to add a 7th, this error pops up and the update method fails.
The full error log, with my unique property data is:
Error: Reference.update failed: First argument path specified exceeds the maximum depth that can be written (32) or object contains a cycle in property
'users.sIRf7m1uWfa9j0iF6UuuzvdD5TG2.dishcategories.default01.dishes.u3o1p278vriqo3odeslle.categories.0.dishes.irdrl2q7blsi1y7ih3jhh.categories.0.dishes.v8pl7r9llhfp7sqmz7uikk.categories.0.dishes.2ee3ajy6d5vymneewgflze.categories.0.dishes.btdib119nz5cnm6zk5uu4t.categories.0.dishes.4wyu5yqyn2z0bgvcejix9.categories.0.dishes.w1cfcpktym7nkp76p521n.categories.0.createdDate'
at ValidationPath.checkValid_ (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1035:19)
at ValidationPath.push (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1015:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1478:18
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
at validateFirebaseData (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1462:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1479:13
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
at validateFirebaseData (/srv/node_modules/#firebase/database/dist/index.node.cjs.js:1462:14)
at /srv/node_modules/#firebase/database/dist/index.node.cjs.js:1479:13
at Object.forEach (/srv/node_modules/#firebase/util/dist/index.node.cjs.js:837:13)
Here's the cloud function code from index.ts:
// Now we need to check if this dish's categories already exist as user categories.
// If they do, we can add this newly created dish into them.
// If they don't, we can create them with this newly added dish in them.
dish.categories.forEach( async (dishCategory) => {
const index = objectInArrayByID(dishCategory, userCategories)
if ( index !== -1 ) {
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish) // *** This is the update method producing the error in this case ***
}
else {
await userCategoriesRef.child(`${dishCategory.id}`).update(dishCategory)
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish)
}
})
Anyone know what this error means, and perhaps what I'm doing wrong here? Thanks!
The error message is quite explicit: you're trying to write data that is more than 32 levels deep, or which contains a cyclic object.
Given the code you shared, the latter seems most likely: you're looping over each category of a dish, and then write that dish to each category again. The simplest fix I can think of is to write the dish-without-categories to each category:
dish_without_categories = dish;
delete dish_without_categories.categories;
dish.categories.forEach( async (dishCategory) => {
const index = objectInArrayByID(dishCategory, userCategories)
if ( index !== -1 ) {
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish_without_categories)
}
else {
await userCategoriesRef.child(`${dishCategory.id}`).update(dishCategory)
return userCategoriesRef.child(`${dishCategory.id}/dishes/${id}`).update(dish_without_categories)
}
})

nodejs+selenium-driver NoSuchElementError & StaleElementReferenceError

I am doing a test based mocha. node v8.2.1, selenium-webdriver: ^3.5.0.
test.it('demoClass', () => {
driver.classes[0].findElement(By.css('.class-avatar')).click();
driver.wait(until.elementIsVisible(driver.findElement(By.css('.anticon.anticon-plus'))));
//driver.sleep(2000);
driver.findElement(By.css('.anticon.anticon-plus')).click();
})
I am getting two different types of errors, either its NoSuchElementError: no such element: Unable to locate element: or StaleElementReferenceError: stale element reference: element is not attached to the page document
But whichever error, its refer to line:
driver.findElement(By.css('.anticon.anticon-plus')).click();
When I use driver.sleep(2000), its getting resolved. In my opinion, It's the question of animation. I can get the element(.anticon.ancicon-plus) only at the time, the page's animation is completed.
what I am confused is that I use driver.wait(until.elementIsVisible()) without an error, It's obvious that I got the element. but at the next line, I can't use it. Or NoSuchElementError, or StaleElementReferenceError.
I find some answer like http://www.seleniumhq.org/exceptions/stale_element_reference.jsp,https://stackoverflow.com/questions/18225997/stale-element-reference-element-is-not-attached-to-the-page-document. But It can't help me.
when use driver.findElement, something terrible will be triggered. use javascript instead it.
driver.executeScript(function() {
while(true) {
if(!document.querySelector('.anticon.anticon-plus')){}
else {
document.querySelector('.anticon.anticon-plus').click();
break;
}
}
return true; // not neccessary
})

jquery Validation Engine funcCall not working if only rule

I have an input field that I am trying to add custom validation to (required depending on another field). If I put required AND funcCall() I can see that two errors are returned. If I only put the funcCall nothing is returned. I know it's getting in the function and the condition because I did a console.log() but for some reason it seems like it needs an initial rule to fail to show the error.
Call:
<input type="text" class="validate[funcCall[validatePassportRequired]]" id="form_register_passport_number" value="" name="passport_number" size="50">
Function:
function validatePassportRequired(field, rules, i, options) {
if ($('#register_for').val()!='Local') {
return options.allrules.required.alertText;
}
}
So If I change the Call to:
class="validate[required, funcCall[validatePassportRequired]]"
I get two * This field is required
Do I have to have another validation rule along with the funcCall?
just add the following line before returning the error message and instead of required in returning message put the function name before .alertText.
rules.push('required');
#sunzyflower in your case your function would see like this..
function validatePassportRequired(field, rules, i, options) {
if ($('#register_for').val()!='Local') {
rules.push('required');
return options.allrules.validatePassportRequired.alertText;
}
}
Use
funcCallRequired[validatePassportRequired]
instead of
funcCall[validatePassportRequired]
This will add required internally without having a double message.
If you want more information about the (old) issue :
https://github.com/posabsolute/jQuery-Validation-Engine/issues/392
https://github.com/posabsolute/jQuery-Validation-Engine/pull/785

Resources