Test if a redux connected component is rendered - reactjs

I have this presentational component that includes a LoginForm which uses redux connect... when i try to see if the component is there by using wrapper.debug(), instead of the component i see: <Connect(Component) />
What do i have to do in order to see the actual LoginForm and test its length?
This is my component:
const LoginSection = ({ intl }) => (
<div className={styles.loginSection}>
<div className={styles.wrapper}>
<div className={styles.form}>
<p className={styles.title}>
<FormattedMessage
id="Dashboard.login.title"
defaultMessage="Login to an account"
/>
</p>
<LoginForm />
<p className={styles.createAccountWrapper}>
<span className={styles.dontHaveAccount}>
<FormattedMessage
id="Dashboard.login.subline"
defaultMessage="Dont have an account?"
/>
</span>
<a
className={styles.createAccount}
href={`${localeToDomainMap[intl.locale]}/register`}
>
<span className={styles.createOneHere}>
<FormattedMessage
id="Dashboard.login.createAccount"
defaultMessage="Create one here."
/>
</span>
</a>
</p>
</div>
</div>
</div>
);
and this is my test:
const setup = (newProps) => {
const props = {};
const wrapper = shallow(<LoginSection {...props} />);
return {
wrapper,
props,
};
};
describe('LoginSection', () => {
test('that it contains LoginForm', () => {
const { wrapper } = setup();
console.log(wrapper.debug());
expect(wrapper.find('.loginFrom')).toEqual(1);
});
});
and this is the result of wrapper.debug():
<div className="loginSection">
... other stuff here ...
<Connect(Component) />
... other stuff here ...
</div>

Related

React change css style of a div in another component by button clicking in another component

on my Project I have a banner on top of my site with 2 buttons. when I click the button profile I want it to change the css style of a div in another component.
this is my code for the banner:
import Profile from "./Profile";
function Banner() {
const invis=false;
return (
<div className="banner">
<span className="bannerbtnsettings">
<button className="btnbannersettings">Settings</button>
</span>
<span className="bannerbtnprofile">
<button className="btnbannerprofile" onClick={Profile.changeStyle}>Profile</button>
</span>
</div>
);
}
export default Banner;
this is my code for the div in the other component:
import "../index.css";
import React, { useState } from "react";
const Profile = () => {
const [style, setStyle] = useState("profile-hidden");
const changeStyle = () => {
console.log("you just clicked");
setStyle("profile-displayed");
};
return (
<div>
<div className={style}> hellllo</div>
</div>
);
};
export default Profile;
I can only find information about this with parent-child components.
They said I should use a usestate import but I can't seem to get it working. what's the proper way to do this?
All you need is lift your state to parent component, if you have a long trip to your common ancestor you can try to use a context. Attached a working example. Hope it helps!
const Banner = ({ onClickHandler }) => {
return (
<div className="banner">
<span className="bannerbtnsettings">
<button className="btnbannersettings">Settings</button>
</span>
<span className="bannerbtnprofile">
<button className="btnbannerprofile" onClick={() => onClickHandler()}>Profile</button>
</span>
</div>
)}
const Profile = ({ style }) => {
return (
<div>
<div className={style}>I'm your profile :)</div>
</div>
);
};
const App = () => {
// We lift the state
const [style, setStyle] = React.useState("profile-hidden");
const profileHandler = () => {
setStyle(style === 'profile-hidden'
? 'profile-displayed'
: 'profile-hidden')
}
return(
<div>
<Banner onClickHandler={profileHandler} />
<Profile style={style} />
</div>
)
}
// Render
ReactDOM.createRoot(
document.getElementById("root")
).render(
<App />
);
.profile-hidden {
display: none;
}
.profile-displayed {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
<div id="root"></div>
You cannot use this syntax for React Components COMPONENT.method
, in your case onClick={Profile.changeStyle} !
Instead you should make Banner parent component and use Profile component as child inside it or vise versa !
then You should pass the state style as props so then you will be able to use its value.
your code should look like this :
function Banner() {
const [style, setStyle] = useState("profile-hidden");
const changeStyle = () => {
console.log("you just clicked");
setStyle("profile-displayed");
};
return (
<div className="banner">
<span className="bannerbtnsettings">
<button className="btnbannersettings">Settings</button>
</span>
<span className="bannerbtnprofile">
<button className="btnbannerprofile" onClick={changeStyle}>Profile</button>
</span>
<Profile style={style} />
</div>
);
}
export default Banner;
and your Profile component :
const Profile = (props) => {
return (
<div>
<div className={props.style}> hellllo</div>
</div>
)
}

How do I test that my component has a specific className?

Take the following React component. It renders some text and an accordion.
const AccountDetails = ({
accountNumber,
accountType,
accordionOpen,
accordionState,
productName,
toggle,
}) => {
if (accordionState) {
return (
<div className="transaction-card-account-info">
<div className={`icon ${accountTypeIcons[accountType]}`} />
<div className="account-details">
<div className="account-name">{productName}</div>
{accountNumber && <div>{`Account ${accountNumber}`}</div>}
</div>
</div>
);
} else {
return (
<div className="transaction-card-account-info">
<div className={`icon ${accountTypeIcons[accountType]}`} />
<div className="account-details">
<div className="account-name">
{productName}
<ToggleAccordionButton
onClick={toggle}
>
{accordionOpen ? <CloseAccordionIcon /> : <OpenAccordionIcon />}
</ToggleAccordionButton>
</div>
{accountNumber && <div>{`Account ${accountNumber}`}</div>}
</div>
</div>
);
}
};
AccountDetails.propTypes = AccountDetailsPropTypes;
export default AccountDetails;
`openAccordionIcon` renders the following HTML
`
<button type="button" class="sc-hBURRC jZGdVy">
<i class="sc-fotPbf bdlDTo fas fa-chevron-right"></i>
</button>
`
I'm trying to test that the className of 'fa-chevron-right' is present. I've looked at several Stackoverflow posts as well as documentation for React Testing Library, Enzyme, and Jest and nothing seems to work. Below is my test file.
describe('<AccountDetails />', () => {
let defaultProps;
beforeEach(() => {
defaultProps = {
accountNumber: '4571184999',
accountType: 'generic',
accordionOpen: true,
accordionState: false,
productName: 'Alex Credit',
toggle: PropTypes.func,
};
});
test('should render correctly', () => {
const { getAllByText } = render(<AccountDetails {...defaultProps} />);
expect(getAllByText('Alex Credit').length).toBe(1);
});
test('should call toggle correctly', () => {
// this test fails
const wrapper = render(<AccountDetails {...defaultProps} />);
expect(wrapper.getElementsByClassName("fa-chevron-right").length).toBe(1);
});
How can I test that the component renders fa-chevron-right?
You could use by adding jest-dom to your project.
It becomes:
expect(container).toHaveClass('fa-chevron-right');
I solved it by adding a data-testid='down' to my component. I don't love that I need to add an attribute just to test it, but it's the only way I could solve it. I used React's Testing-library.
return (
<div className="transaction-card-account-info">
<div className={`icon ${accountTypeIcons[accountType]}`} />
<div className="account-details">
<div className="account-name">
{productName}
<ToggleAccordionButton
onClick={toggle}
>
{accordionOpen ? <CloseAccordionIcon data-testid="down" /> : <OpenAccordionIcon />}
</ToggleAccordionButton>
</div>
{accountNumber && <div>{`Account ${accountNumber}`}</div>}
</div>
</div>
);
// test
test('should call toggle correctly', () => {
const { container } = render(<AccountDetails {...defaultProps} />);
expect(getByTestId(container, 'down')).toBeTruthy();
});

React child component not executing functional parent component function

I have this Footer child, which has the Modal parent's cancel function passed to it in the props, but it won't execute the parent's "handleCancel" function.
const PageFooter = (props) => {
const { handleCancel} = props;
const modalStyleClass = useModalStyles();
return(
<footer className={modalStyleClass.modalFooter}>
<div className="container-fluid">
<div className="row">
<div className="col-sm-6">
</div>
<div className="col-sm-6 text-right">
<button className={modalStyleClass.cancelButton}
onClick={handleCancel}>
</button>
</div>
</div>
</div>
</footer>
)}
export default PageFooter;
The generic edit modal parent get's it's props from whatever other parent component called it: That parent implements the state of the modal
with
const [isModalShown, toggleModal] = React.useState(false);
The generic 'EditModal' as parent to the child footer component's code:
export function GenericEditModal (props) {
const {isModalShown, title, closeModal, } = props;
const HandleCancel = () => {
closeModal();
};
return (
<form >
<div>
<Modal
className={modalStyleClass.modal}
open={isModalShown}
closeModal={handleCloseModal}
onClose={handleCloseModal}
>
<div className={modalStyleClass.paper} style={{ top: '0px',padding:'0px', }} >
<ModalHeader>
handleCancel={HandleCancel}
</ModalHeader>
{ markup }
</div>
<Footer>
handleCancel={HandleCancel}
</Footer>
</div>
</Modal>
</div>
</form>
);
};
export const GenericEditModal = React.memo(GenericEditModal);
Pass to child like this:
<Footer handleCancel={HandleCancel}/>

How can remove an attribute from a React component?

I am unable to modify this section of code.
const DisplayTheSecret = props => (
<div>
<span aria-hidden="true">
The secret to life is {props.secretToLife}.
</span>
</div>
);
How can I remove the attribute aria-hidden from it?
HTML
<div id="app"></div>
JS file
const DisplayTheSecret = props => (
<div>
<span aria-hidden="true">
The secret to life is {props.secretToLife}.
</span>
</div>
);
const withSecretToLife = (WrappedComponent) => {
class HOC extends React.Component {
render() {
return (
<WrappedComponent
{...this.props}
secretToLife={42}
// like to remove aria-hidden or set it to aria-hidden="false"
/>
);
}
}
return HOC;
};
const Life = withSecretToLife(DisplayTheSecret);
ReactDOM.render(<Life />, document.querySelector("#app"))

Countries End point is not returning anything although works in sandbox

I am building a small Countries App in React. The issue I have is that I have changed the endpoint and now it is not returning anything. I checked this in Sandbox and it worked fine. Below is the code for the page that renders the details of the country.
import React from 'react';
import { useEffect } from "react";
import { useState } from "react";
import { NavBarCard } from '../NavBar/NavBarCard';
import './DetailCountryCard.css';
import {Link} from 'react-router-dom';
function DetailCountryCard ({ match }) {
useEffect(() => {
fetchItem();
console.log(match);
// eslint-disable-next-line
}, []);
const [country, setCountry] = useState({});
const [darkMode, setDarkMode] = useState(false);
const fetchItem = async () => {
const fetchItem = await fetch(
`https://restcountries.eu/rest/v2/alpha/${match.params.alpha3Code}`
);
const country = await fetchItem.json();
setCountry(country);
console.log(country);
};
return (
// <div>
// <h1>the country</h1>
// </div>
<div className={darkMode ? "dark-mode" : "light-mode" }>
<NavBarCard handlechange={()=> setDarkMode(prevMode => !prevMode)} moonMode={darkMode ? "moon fas fa-moon" :
"moon far fa-moon"}
darkMode={darkMode ? "dark-mode" : "light-mode"}/>
<div className="detailCard">
<Link to="/">
<button className="topButton myButton">Back</button>
</Link>
<div className="container">
<img className="flag" alt="flag" src={country.flag} />
<div className="countryName">
<div className="NativeName">
<h1 className="Country">{country.name}</h1>
<h2>Native Name:</h2>
<p> {country.nativeName}</p>
<br />
<h2>Population:</h2>
<p> {country.population}</p>
<br />
<h2>Region:</h2>
<p> {country.region}</p>
<br />
<h2>Sub Region:</h2>
<p> {country.subregion}</p>
<br />
<h2>Capital:</h2>
<p> {country.capital}</p>
<br />
<div>
<h2>Border Countries:</h2>{country.borders && country.borders.map(function(border){
return(
<Link to={`/DetailCard/${border}`}>
<button className="myButton"> {border} </button>
</Link>
)
})}
</div>
</div>
</div>
<div className="domain">
<h2>Top Level Domain: </h2>
<p>{country.topLevelDomain}</p>
<br />
<h2>Currencies: </h2>
<p>{country.currencies && country.currencies.map(({ name }) => name).join(", ")}</p>
<br />
<h2>Languages: </h2>
<p>{country.languages && country.languages.map(({ name }) => name).join(", ")}</p>
<br />
</div>
</div>
</div>
</div>
);
}
export default DetailCountryCard;
All I get is blank page and in the console it saying that I am getting a status of 400. Any help would be appreciated. If I just put bra as the last three letters of the alpha code this is what I get.

Resources