TestingLibraryElementError: Unable to find an element Conditional based data-testid in #testing-library/react - unit-testing

I have written many test cases in the react testing library, I got stuck in the accessing condition based DOM element. I have tried many ways using import { renderHook } from '#testing-library/react-hooks'. But didn't work from me. Here is the code. Great appreciate
import axios from "axios";
import { withTranslation } from "react-i18next";
function MDStaticContent({ t }) {
const [promoArrayIsValid, setPromoArrayIsValid] = useState(false);
const loadRecent = async () => {
API Calls Here
const recents = await onRecentMedia(accounts[0], instance);
if (Some condition) {
if (Here Some condition) {
setPromoArrayIsValid(true);
}
dispatch(Here Will discpatch data);
}
};
return (
<>
{ promoArrayIsValid && (
<div data-testid="mdStaticContent">
Hello
</div>
</>
)}
}
import React from "react";
import { render, cleanup } from "#testing-library/react";
import { useEffect, useState } from "react";
import { Provider } from 'react-redux';
import "#testing-library/jest-dom/extend-expect";
import { MemoryRouter } from 'react-router-dom';
import configureMockStore from 'redux-mock-store';
import { ThemeProvider } from 'styled-components';
import thunk from 'redux-thunk';
import MDStaticContent from "./MDStaticContent";
import { act } from 'react-dom/test-utils';
import MockAPIData from '../resources/locales/en/MockAPIData.json';
import { renderHook } from '#testing-library/react-hooks'
const mockStore = configureMockStore([thunk]);
let data = {
mediaArrayIsValid: true,
promoArrayIsValid: true
}
const store = mockStore(data);
it("should take a snapshot and match of MDStaticContent Page", () => {
const { asFragment, getAllByTestId, getByTestId
} = render(
<ThemeProvider theme={theme}>
<Provider store={store}>
<MemoryRouter>
<MDStaticContent/>
</MemoryRouter>
</Provider>
</ThemeProvider>
);
expect(asFragment()).toMatchSnapshot();
expect(getAllByTestId("mdStaticContent")).toHaveLength(1);
expect(getByTestId("mdStaticContent")).toBeVisible();
});

Related

How to access authData in AWS Amplify Authenticator Component in React Native?

I am following the instructions at: https://docs.amplify.aws/ui/auth/authenticator/q/framework/react-native/#using-the-authenticator-component
I can get things working, mostly. I can access authState inside of onStateChange as well, but I cannot figure out how to access authData so I can get things like username, etc.
Could someone please provide an example of how this is done?
Here is my code now:
import { StyleSheet, Text, Button,View,Platform,StatusBar,Image, TouchableWithoutFeedback, SafeAreaView } from 'react-native';
import {useState} from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { useNavigationContainerRef } from '#react-navigation/native';
import Ionicons from 'react-native-vector-icons/Ionicons';
// Screens
import Browsescreen from './screens/Browsescreen';
// AWS
import { Authenticator } from 'aws-amplify-react-native/dist/Auth';
const Tab = createBottomTabNavigator();
function App() {
const navigationRef = useNavigationContainerRef();
const [showLoggedInPage, setLoggedInPage] = useState(false);
const loggedInPage = showLoggedInPage ? (
<SafeAreaView style={styles.container}>
<StatusBar style="auto" />
<View>
[REMOVED]
</View>
<NavigationContainer ref={navigationRef}>
<Tab.Navigator>
[REMOVED]
</Tab.Navigator>
</NavigationContainer>
</SafeAreaView>
) : null;
return (
<Authenticator
onStateChange={(authState) => {
console.log(authState)
if (authState == "signedIn") {
setLoggedInPage(true);
} else {
setLoggedInPage(false);
}
}
}
hideDefault={false}
>
{loggedInPage}
</Authenticator>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ddd',
},
});
export default App;
Please remember I am new so simple answer with sample if possible please. Thank you.

JEST unit testcase - beginner and facing issues

im trying to to convert below code snippet to JEST unit testing but its throwing error please help me out in resolving it
import React from 'react'
import { BrowserRouter as Router, Switch, Route} from 'react-router-dom';
import IdleTimer from 'react-idle-timer';
import { ApolloProvider } from '#apollo/react-hooks';
import Dashboard from '../pages/Dashboard';
import Loader from '../components/Loader';
import Alert from '../components/Alert';
import NoAccess from '../pages/NoAccess';
import { GQL } from '../services/GQL';
import { IdleTimeOutModal } from './IdleTimeoutModal';
import PropTypes from 'prop-types';
import 'bootstrap/dist/css/bootstrap.min.css';
import '../App.scss';
import '../assets/css/loader.scss';
import AuthenticatedRoute from '../guards/AuthenticatedRoute';
import auth from '../services/Auth';
import { connect } from 'react-redux';
class Layout extends React.Component {
constructor(props){
super(props);
this.state = {
timeout:1000 * 900 * 1,
showModal: false,
userLoggedIn: window.localStorage.getItem('loginUser'),
isTimedOut: false,
}
this.idleTimer = null
this.onAction = this._onAction.bind(this)
this.onActive = this._onActive.bind(this)
this.onIdle = this._onIdle.bind(this)
this.handleClose = this.handleClose.bind(this)
this.handleLogout = this.handleLogout.bind(this)
}
_onAction(e) {
// console.log('user did something', e)
this.setState({isTimedOut: false})
}
_onActive(e) {
// console.log('user is active', e)
this.setState({isTimedOut: false})
}
_onIdle(e) {
// console.log('user is idle', e)
const isTimedOut = this.state.isTimedOut
if (isTimedOut) {
this.setState({showModal: false})
window.localStorage.setItem('loginUser', 'false');
} else {
this.setState({showModal: true})
this.idleTimer.reset();
this.setState({isTimedOut: true})
}
}
handleClose() {
this.setState({showModal: false})
}
handleLogout() {
this.setState({showModal: false})
auth.signout();
}
render(){
// console.log(window.location)
const {match} = window.location.href;
// const { match } = this.location
return(
<>
<IdleTimer
ref={ref => { this.idleTimer = ref }}
element={document}
onActive={this.onActive}
onIdle={this.onIdle}
onAction={this.onAction}
debounce={250}
timeout={this.state.timeout} />
<div className="">
<ApolloProvider client={GQL}>
<Router>
<Switch>
{/* <Route component={NoAccess} path="/no-access" exact={true} /> */}
<AuthenticatedRoute path={`${window.location.pathname}`} component={Dashboard} />
</Switch>
</Router>
{/* <Loader isOpen={loader.isLoading} /> */}
{/* <Alert /> */}
</ApolloProvider>
<IdleTimeOutModal
showModal={this.state.showModal}
handleClose={this.handleClose}
handleLogout={this.handleLogout}
/>
</div>
</>
)
}
}
***JEST throwing error while converting to JEST - ShallowWrapper::state() can only be called on class components
jest help***
export default connect((props) =>({
match: props.uiel.isRequired,
history: props.uiel.isRequired
}))(Layout);
import React from 'react';
import { BrowserRouter as Router, Switch, Route} from 'react-router-dom';
import { render, cleanup, fireEvent } from '#testing-library/react';
import '#testing-library/jest-dom/extend-expect';
import Enzyme, { shallow, mount } from 'enzyme';
import Layout from './Layout';
import Adapter from 'enzyme-adapter-react-16';
import { Provider } from "react-redux";
import configureMockStore from "redux-mock-store";
import { IdleTimeOutModal } from './IdleTimeoutModal';
import { wrap } from 'module';
Enzyme.configure({ adapter: new Adapter() })
const mockStore = configureMockStore();
let handleLogout:any;
let showModal: any;
let handleClose:any;
let remainingTime:any;
let _onAction:any;
let _onIdle:any;
let _onActive:any;
let idleTimer:any;
describe("Render Layout Component", ()=>{
let store;
let wrapperlayout:any;
beforeEach(()=>{
store = mockStore({
loader: false
});
wrapperlayout = shallow(
<Provider store={store}>
<Layout />
</Provider>
);
});
it('should render the value of color', () => {
wrapperlayout.setProps({ timeout:1000 * 900 * 1 });
wrapperlayout.setProps({ showModal: false });
wrapperlayout.setProps({ userLoggedIn: window.localStorage.getItem('loginUser') });
wrapperlayout.setProps({ isTimedOut: false });
//expect(wrapper.state('color')).toEqual('transparent');
});
it("should increment index - function test", () => {
//const app = shallow(<Normal />);
expect(wrapperlayout.state("isTimedOut")).toEqual('false');
wrapperlayout.instance()._onAction();
expect(wrapperlayout.state("isTimedOut")).toEqual('false');
});
test("Render Modal Layout", ()=>{
expect(wrapperlayout.exists()).toBe(true);
});
});

Need to write a unit test for service on Jest

Help me fix the error, and if possible improve the test itself, because it will be based on further tests for services.
I hope for your help
This is my service file
import { Injectable } from '#nestjs/common';
import { InjectRepository } from '#nestjs/typeorm';
import { createQueryBuilder, getConnection, getRepository, Repository, getManager, Connection } from 'typeorm';
import { Brands } from './brands/brands.entity';
import { Categories } from './categories/categories.entity';
import { Volumes } from './volumes/volumes.entity';
import { Packages } from './packages/packages.entity';
import { Tags } from './tags/tags.entity';
import { Countries } from './countries/countries.entity';
import { Sub_categories } from './sub_categories/sub_categories.entity';
import { Products } from './products.entity';
import { IProduct } from './products.interface';
import { Collections } from './collections/collections.entity';
#Injectable()
export class ProductsService {
constructor(
#InjectRepository(Products)
private productRepository: Repository<Products>,
) {}
private readonly products: IProduct[] = [];
async findAllProductsByCategory(category: string): Promise<IProduct[]> {
const qb = getRepository(Products).createQueryBuilder("products");
const subQuery: string = qb.subQuery()
.select('categories.id', 'cat_id')
.from(Categories, 'categories')
.where(`cat_id = '${ category }'`)
.getQuery()
return await this.findAllProductsByArgument( 'category_id', subQuery );
}
async findAllProductsByArgument(argumentId1: string, subQuery1: string, argumentId2?: string, subQuery2?: string): Promise<IProduct[]> {
const qb = getRepository(Products).createQueryBuilder("products");
qb
.select(
`*,
Products.brand_id AS brand_id`
)
.addSelect('brands.brand_name', 'brand_name')
.addSelect('brands.brand_id', 'brand_nameid')
.addSelect('categories.cat_name', 'cat_name')
.addSelect('categories.cat_id', 'cat_id')
.addSelect('volumes.volume_name', 'volume_name')
.addSelect('volumes.volume_id', 'volume_id')
.addSelect('tags.name', 'tag_name')
.addSelect('tags.tag_id', 'tag_nameId')
.addSelect('sub_categories.subcat_name', 'subcategory_name')
.addSelect('sub_categories.subcat_id', 'subcategory_id')
.addSelect('packages.package_name', 'package_name')
.addSelect('packages.package_id', 'package_nameId')
.addSelect('countries.country_name', 'country_name')
.addSelect('countries.country_id', 'country_nameId')
.addSelect('Products.price', 'price_by_one')
.innerJoin(Brands, 'brands', 'Products.brand_id = brands.id')
.innerJoin(Categories, 'categories', 'Products.category_id = categories.id')
.innerJoin(Volumes, 'volumes', 'Products.volume_id = volumes.id')
.innerJoin(Tags, 'tags', 'Products.tag_id = tags.id')
.innerJoin(Sub_categories, 'sub_categories', 'Products.sub_category_id = sub_categories.id')
.innerJoin(Packages, 'packages', 'Products.package_id = packages.id')
.innerJoin(Countries, 'countries', 'Products.country_id = countries.id')
.where('Products.stock > Products.pack_quantity AND isshow = true')
.andWhere(`Products.${ argumentId1 } = ${ subQuery1 }`);
if(argumentId2 && subQuery2){
qb.andWhere(`Products.${ argumentId2 } = ${ subQuery2 }`)
}
return qb.getRawMany();
}
}
I don't really understand how to mocking data and simulate functions
import { Test, TestingModule } from '#nestjs/testing';
import { getRepositoryToken } from '#nestjs/typeorm';
import { Repository } from 'typeorm';
import { Products } from './products.entity';
import { ProductsService } from './products.service';
class ProductsFake {
public async find(): Promise<void> {}
}
describe('ProductsService', () => {
let service: ProductsService;
let repo: Repository<Products>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ProductsService,
{
provide: getRepositoryToken(Products),
useClass: ProductsFake
}
]
}).compile();
service = module.get(ProductsService);
repo = module.get(getRepositoryToken(Products));
});
describe('finding a products', () => {
it('should be defined', async () => {
expect(service).toBeDefined();
});
it('return the products list', async () => {
const product = new Products();
const mockData = {
id: 10,
brand_name: "Brewdog",
brand_nameid: "brewdog",
cat_id: "pivo"
};
Object.assign(product, mockData);
const productsRepositoryFindAll = jest
.spyOn(repo, 'find')
.mockResolvedValue([product]);
const result = await service.findAllProductsByCategory( 'pivo' );
expect(result[0]).toBe(product);
expect(productsRepositoryFindAll).toBeCalled()
});
});
});
This is an error that appears when trying to test
йййййййййййййййййййййййййййййййййййййййййййййййййййййййййййййййййййййййййййййййй

How to get UserId and set it as a global variable using useContext, useState and useEffect in React-Native?

I have an app built with React-Native, Amplify, AppSync and Cognito and when it loads I would like to save the USER ID and USER TYPE as a global state that can be accessed on every screen.
The user id and user type (Teacher or Student) will never change as these are created on signup.
import React, { useEffect, useState, useReducer } from 'react';
import {AppRegistry} from 'react-native';
import {name as appName} from './app.json';
import App from './src/AppNavigation';
import Amplify, { API, graphqlOperation, Auth } from 'aws-amplify';
import awsmobile from './aws-exports';
import { getUser } from './src/graphql/queries';
Amplify.configure(awsmobile);
export const UserContext = React.createContext()
function MyApp() {
const [userContext, setUserContext] = useState({})
const getUserIdAndType = async () => {
try {
// get User data
const currentUser = await Auth.currentAuthenticatedUser();
const userId = await currentUser.signInUserSession.accessToken.payload.sub;
// get user data from AppSync
const userData = await API.graphql(graphqlOperation(getUser, { id: userId }));
setUserContext({ userId: userId, userType: userData.data.getUser.userType })
} catch (err) {
console.log('error', err);
}
}
useEffect(() => {
getUserIdAndType()
}, [])
return (
<UserContext.Provider value={userContext}>
<App />
</UserContext.Provider>
);
}
AppRegistry.registerComponent(appName, () => MyApp);
Then when I want to use the context state I do as follows:
import { useContext } from 'react';
import { UserContext } from '../../../index';
function Loading ({ navigation }) {
const userContext = useContext(UserContext)
if (userContext.userId != '') {
navigation.navigate('AppTabs');
} else {
navigation.navigate('Auth');
}
}
export default Loading;
Or to get which screen to show (Teacher or Student)...
import { useContext } from 'react';
import { UserContext } from '../../../index';
function LoadingProfile ({ navigation }) {
const userContext = useContext(UserContext)
if (userContext.userType === 'Teacher') {
navigation.navigate('TeacherScreen');
} else if (userContext.userType === 'Student') {
navigation.navigate('StudentScreen');
}
}
export default LoadingProfile;
When the app loads it says the userContext.userId and userContext.userType are empty so it is not saving the state when I set it in the getUserIdAndType() function.
-
****** If I rewrite the App file (INSTEAD OF USING THE HOOKS useState, useEffect) I just declare the values then it works... so I am obviously not using the hooks or async getUserIdAndType() correctly. ******
import React, { useEffect, useState, useReducer } from 'react';
import {AppRegistry} from 'react-native';
import {name as appName} from './app.json';
import App from './src/AppNavigation';
import Amplify, { API, graphqlOperation, Auth } from 'aws-amplify';
import awsmobile from './aws-exports';
import { getUser } from './src/graphql/queries';
Amplify.configure(awsmobile);
export const UserContext = React.createContext()
function MyApp() {
const userContext = {
userId: '123456789', // add the user id
userType: 'Teacher', // add the user type
}
return (
<UserContext.Provider value={userContext}>
<App />
</UserContext.Provider>
);
}
AppRegistry.registerComponent(appName, () => MyApp);
change this :
<UserContext.Provider value={{userContext}}>
<App />
</UserContext.Provider>
to this :
<UserContext.Provider value={userContext}>
<App />
</UserContext.Provider>
you've added an extra curly bracket " { "

redux saga put not dispatching action

I'm trying to to do integration tests, by mounting a smart connected component.
The fetch action that is within componentDidMount of my smart components dispatches just fine, and it's taken by my Saga. Although it is supposed to put a success action, it doesn't .
Here is my testing code :
import React from 'react'
import { Provider } from 'react-redux'
import configureMockStore from 'redux-mock-store'
import MockAdapter from 'axios-mock-adapter'
import Enzyme,{ mount,render } from 'enzyme'
import Tasks from '../containers/tasks.jsx'
import createSagaMiddleware from 'redux-saga'
import axios from "axios";
import Adapter from 'enzyme-adapter-react-16';
import mySaga from '../actions/tasksSaga'
import { createStore, combineReducers, applyMiddleware } from 'redux'
import reducer from '../reducers'
Enzyme.configure({ adapter: new Adapter() });
describe('App', () => {
// create the saga middleware
const sagaMiddleware = createSagaMiddleware()
const mock = new MockAdapter(axios)
const state = {
tasksReducer:{
tasks:[]
},
uiReducer :{
}
};
const todos = [
{
id: 1,
title: 'todo1',
description: 'nice'
},
{
id: 2,
title: 'todo2',
description: 'nice'
}
]
beforeAll(() => {
mock.onGet('http://localhost:9001/tasks').reply(200, {tasks:todos})
})
it('renders an App container', () => {
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware),
)
sagaMiddleware.run(mySaga)
const wrapper = mount(
<Provider store={store}>
<Tasks />
</Provider>
)
wrapper.instance().forceUpdate()
expect(wrapper.find('Task')).toHaveLength(3)
})
})
My success action is never called although data is good.