setup() not triggered when testing Vue Components (composition-api) - javascript

I’m using vue 2.6 with #vue/compisiton-api.
import { createLocalVue, shallowMount } from '#vue/test-utils';
import VueCompositionApi from '#vue/composition-api';
import Page from '#/components/templates/Page.vue';
import Component from './Component.vue';
const localVue = createLocalVue();
localVue.use(VueCompositionApi);
jest.mock('#vue/composition-api', () => ({
reactive: jest.fn().mockReturnValue({
isFetchingData: true,
}),
computed: jest.fn(),
watch: jest.fn(),
}));
describe('Component', () => {
it('test', async () => {
const wrapper = shallowMount(Component, {
localVue,
stubs: {
Page,
},
});
expect(wrapper.findComponent(Page).exists()).toBe(true);
});
});
For some reason when I shallowMount Component the setup() method is not triggered. Is there any specific extra config needed for that?
Thanks in advance

That's an old question, but maybe someone will stumble upon it like me.
My solution was to register the composition-api plugin just like you do it with Vuex:
import VueCompositionAPI from '#vue/composition-api'
const localVue = createLocalVue()
localVue.use(VueCompositionAPI)
return shallowMount(YourComponent, {
localVue,
// [...]
})

Related

Testing React/Jest component with Window.onload

I'm testing a functional component that uses Window.onload to stay on a certain page. Example of the code
function SignUpForm(props) {
const history = useHistory();
const {setOnPage } = props;
window.onload = setOnPage("/registrarse")
My test is:
import React from 'react'
import Enzyme from "enzyme";
import { screen, render } from '#testing-library/react'
import SignInScreen from './SignInScreen'
import Adapter from "enzyme-adapter-react-16"
const { shallow } = Enzyme;
Enzyme.configure({ adapter: new Adapter() })
describe('Test for login in form', () => {
test("renders correctly", () => {
shallow(<SignInScreen/>);
});
});
The error is in the line of Window.onload, I have not been able to find any solution that can help me.
setOnPage is not a function

How to mock useLocation correctly?

I have a component that uses useLocation hook to get the path from the URL.
const { pathname } = useLocation();
useEffect(() => { }, [pathname]);
While I am trying to mock the location using ,
import React from 'react';
import ExampleComponent from './ExampleComponent';
import { fireEvent, render } from '#testing-library/react';
import { shallow } from 'enzyme';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: () => ({
pathname: 'https://URL/'
})
}));
describe('<ExampleComponent />', () => {
it('should render correctly', () => {
shallow(<ExampleComponent />);
});
});
I am getting this error while I run the test,
TypeError: Cannot read property 'location' of undefined
Try mocking the useLocation as jest.fn().mockImplementation
jest.mock('react-router', () => ({
...jest.requireActual("react-router") as {},
useLocation: jest.fn().mockImplementation(() => {
return { pathname: "/testroute" };
})
}));
Below is how I have done this in my tests. * Note I am using typescript
import routeData from 'react-router';
describe('Login Page UnitTests', () => {
const useLocation = jest.spyOn(routeData, 'useLocation');
beforeEach(() => {
useLocation.mockReturnValue({ search: 'testQueryParameters'} as any);
});
// Add unit tests
}
Ensure that you clear the mock to avoid issue with data in subsequent tests
The correct way to mock useLocation is below:
import React from 'react';
import ExampleComponent from './ExampleComponent';
import { fireEvent, render } from '#testing-library/react';
import { MemoryRouter} from 'react-router-dom';
import { shallow } from 'enzyme';
const renderComponent = () => {
return (
<MemoryRouter
initialEntries={["/one", "/two", { pathname: 'https://URL/' }]}
initialIndex={1}>
<ExampleComponent />
</MemoryRouter>
);
}
describe('<ExampleComponent />', () => {
it('should render correctly', () => {
shallow(renderComponent());
});
});

React testing mock variable in functional component

Please help.
I cannot run test because in my util langProvider is package that drops tests.
I have to mock langProvider function or strings variable.
How I can do that?
import React, { ReactElement, useState } from 'react';
import langProvider from 'utils/langProvider';
import { HeaderStyled, DropDownStyled } from './styled';
import './style.scss';
function Header(props: any): ReactElement {
const [state, setState] = useState({
isDropDownOpened: false,
isDrawerOpened: false,
});
const strings = langProvider(props.language, 'components.header');
return (
<HeaderStyled className="header">
...
</HeaderStyled>
);
}
const mapStateToProps = (state: any) => ({
language: state.language,
});
export default connect(mapStateToProps)(Header);
My test file
import { configure, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
import Header from './index';
configure({ adapter: new Adapter() });
describe('<Header />', () => {
const wrapper = shallow(<Header />);
it('My test', () => {
expect('').toEqual('Header');
});
});
not sure, but you can try to insert in your test file before describe function, something like that:
jest.mock("utils/langProvider", () => ({langProvider: ()=> []}));

Jest + react-navigation not locating route / params

I am trying to write a test for an app using react-navigation and I am running into issues of the route and params being read correctly.
I am getting an error of
TypeError: Cannot read property 'params' of undefined
on const [leadId] = useState(route.params.leadId);
my components looks like
export default function AComponent() {
const route = useRoute();
const navigation = useNavigation();
const dispatch = useDispatch();
const [leadId] = useState(route.params.leadId);
}
I have tried following https://callstack.github.io/react-native-testing-library/docs/react-navigation/ but I received Warning: React.createElement: type is invalid when wrapping the component.
My test looks like
import React from 'react';
import { Provider } from 'react-redux';
import { NavigationContainer } from '#react-navigation/native';
import { render, fireEvent, cleanup } from 'react-native-testing-library';
import configureMockStore from 'redux-mock-store';
import AComponent from 'components/contact/AComponent';
const mockStore = configureMockStore([]);
describe('<AComponent />', () => {
let getByTestId, store;
beforeEach(() => {
store = mockStore({});
({ getByTestId } = render(
<Provider store={store}>
<AComponent />
</Provider>
));
});
});
my mock is
jest.mock('#react-navigation/native', () => {
return {
useNavigation: () => ({ goBack: jest.fn() }),
useRoute: jest.fn(),
};
});
I am not sure if I am wrapping the components incorrectly, or if I am missing something else.
Any ideas or help would be greatly appreciated.
Thanks.
Hey I just solved this myself and here is my solution
Change
jest.mock('#react-navigation/native', () => {
return {
useNavigation: () => ({ goBack: jest.fn() }),
useRoute: jest.fn(),
};
});
To
jest.mock('#react-navigation/native', () => ({
...jest.requireActual('#react-navigation/native'),
useNavigation: () => ({ goBack: jest.fn() }),
useRoute: () => ({
params: {
<yourParamName>: '<paramValue>',
<yourParamName2>: '<paramValue2>',
etc...
}
}),
}));
In my case I put this code block into my setup.ts file and then in my jest config inside of package.json I pointed to it.
Example
"setupFiles": [
"./node_modules/react-native-gesture-handler/jestSetup.js",
"./jest/setup.ts"
]
Then in the test itself
const navigation = { navigate: jest.fn() };
const { getByTestId, getByText, queryByTestId } = render(<App navigation={navigation}/>);

Why is this Jest/Enzyme setState test failing for my React app?

Expected:
Test runs and state is updated in the Login component, when then enables the Notification component (error message) to be found
Results:
Test fails, expected 1, received 0
Originally before I added redux and the store, thus needing to use the store and provider logic in my test, this Jest/Enzyme tests were passing.
The Login.test (updated current version)
import React from 'react'
import { Provider } from "react-redux"
import ReactTestUtils from 'react-dom/test-utils'
import { createCommonStore } from "../../store";
import { mount, shallow } from 'enzyme'
import toJson from 'enzyme-to-json'
import { missingLogin } from '../../consts/errors'
// import Login from './Login'
import { LoginContainer } from './Login';
import Notification from '../common/Notification'
const store = createCommonStore();
const user = {
id: 1,
role: 'Admin',
username: 'leongaban'
};
const loginComponent = mount(
<Provider store={store}>
<LoginContainer/>
</Provider>
);
const fakeEvent = { preventDefault: () => '' };
describe('<Login /> component', () => {
it('should render', () => {
const tree = toJson(loginComponent);
expect(tree).toMatchSnapshot();
});
it('should render the Notification component if state.error is true', () => {
loginComponent.setState({ error: true });
expect(loginComponent.find(Notification).length).toBe(1);
});
});
Login.test (previous passing version, but without the Redux store logic)
import React from 'react'
import ReactTestUtils from 'react-dom/test-utils'
import { mount, shallow } from 'enzyme'
import toJson from 'enzyme-to-json'
import { missingLogin } from '../../consts/errors'
import Login from './Login'
import Notification from '../common/Notification'
const loginComponent = shallow(<Login />);
const fakeEvent = { preventDefault: () => '' };
describe('<Login /> component', () => {
it('should render', () => {
const tree = toJson(loginComponent);
expect(tree).toMatchSnapshot();
});
it('should render the Notification component if state.error is true', () => {
loginComponent.setState({ error: true });
expect(loginComponent.find(Notification).length).toBe(1);
});
});
Your problem is that by mixing the redux store logic into the tests, the loginComponent variable no longer represents an instance of Login, but an instance of Provider wrapping and instance of Login.
Thus when you do this
loginComponent.setState({ error: true })
You're actually calling setState on the Provider instance.
I would recommend testing the LoginComponent you've wrapped with connect to produce LoginContainer separately from the store state. The Redux GitHub repo has a great article on testing connected components, which gives a general outline on how to do this.
To summarize what you need to do
Export both LoginComponent and LoginContainer separately
Test LoginComponent individually from the container, essentially doing what your previous working tests before mixing in redux store state did.
Write separate tests for LoginContainer where you test the mapStateToProps, mapDispatchToProps and mergeProps functionality.
Hope this helps!

Categories