Cant test copy from 'copy-to-clipboard' with sinon - reactjs

I'm trying to test my component with Sinon.
It seems I can't simulate the click function which is in the TableMenu component.
TableMenu.jsx
import copy from 'copy-to-clipboard';
const TableMenu = ({onClick, onHide, rowId}) => (
<MenuPopover
onClick={onClick}
onHide={onHide}>
<MenuPopover.Item id={1} onClick={() => copy(rowId)} label='Copy'/>
</MenuPopover>
);
TableMenu.test.js
import copy from 'copy-to-clipboard';
jest.mock('copy-to-clipboard', () => sinon.spy());
it('check method onCopy called', () => {
const wrapper = shallow(<TableMenu {...props}/>);
wrapper.find(MenuPopover.Item).last().props().onClick()
expect(copy.calledOnce).to.eql(true);
});
I'm getting the below error:
Error: Not implemented: window.prompt
at module.exports (C:\adm\node_modules\jsdom\lib\jsdom\browser\not-implemented.js:9:17)
at Window.prompt (C:\adm\node_modules\jsdom\lib\jsdom\browser\Window.js:458:7)
at copy (C:\adm\node_modules\copy-to-clipboard\index.js:58:14)
at Object.onClick (C:\adm\src\TableMenu/TableMenu.jsx:19:43)
...
...
TypeError: reselectPrevious is not a function
at copy (node_modules\copy-to-clipboard\index.js:72:5)
at Object.onClick (src\TableMenu/TableMenu.jsx:19:43)
at Context.<anonymous> (src\TableMenu/TableMenu.test.js:62:62)
at process.topLevelDomainCallback (domain.js:121:23)

I guess this is being discussed in the github repo and the potential solution could be #106 (comment)
Or, just simply mock an implementation for window.prompt. e.g.
jest.spyOn(window, 'prompt').mockImplementation();

Related

how to use spyOn on a class less component

I am trying to apply spyOn to check whether my fucntion download is called on mouse click but I am getting the error. I am already follwoing this question but still no leads. Can anyone tell me where I went wrong. I cannot figure out any clue.
Error
Argument of type '"download"' is not assignable to parameter of type '"context"'.
mcb = jest.spyOn(fileDownlaod.instance(), "download");
my react component is:
const Filer = ({Filey} ) => {
const download = () => {
Filey()
.then((res: Response) => res.blob())
.then((data: Blob) => {
const URL = URL.createObjectURL(data);
});
};
return (
<>
<button
onMouseOver={() => download()}
onClick={() => download()}
>
</button>
</>
);
};
export default Filer;
my jest test is :
import React from 'react';
import Filer from './Filer';
import { mount, ReactWrapper } from 'enzyme';
let filer: ReactWrapper<any>;
describe('Filer', () => {
it('clicked download', () => {
filer = mount(
<Filer />
);
const _download = () => {
//some thing
}
mcb = jest.spyOn(filer.instance(), "download").mockImplementation(_download);
filer.find('button').simulate('click')
expect(mcb.mock.calls.length).toEqual(1);
});
});
If you look at the answer you are already following. In the end it has mentioned that spyOn does not work on functional components inner functions.
This is what has been said:
Keep in mind that any methods scoped within your functional component are not available for spying
So you can spy on props passed.
So the correct implementation that should work, can be:
it('clicked download', () => {
Filey = jest.fn().mockImplementation(_Filey)
filer = mount(
<Filer Filey={Filey}/>
);
expect(Filey).toHaveBeenCalled();
});

How to add test cases for Link using jest /enzyme

I am trying to write some test cases using jest and enzyme,I am unable to add test cases for Link and Please suggest if any more test cases needs to be added
these is styled component, and when should we spy /mock function
displayErr.tsx
export const DisplayErr = React.memo<Props>(({ text, SearchLink }) => (
<Section>
<h1>{text}</h1>
{!SearchLink && <Link to={getPath('SEARCH')}>some text</Link>}
</Section>
));
displayErr.test.tsx
describe('Error Msg', () => {
it('styled component', () => {
const output = mount(<DisplayErr text="hello world" SearchLink={true} />);
const link = output.find(Link).find({ to: '/Search' });
expect(output.find(Section).text()).toEqual('hello world');
//expect(link).toBe('<div class="link">Login</div>');//error
});
});
Here Link will render based on the SearchLink props. As you are passing it as true, it wont be available in the DOM. Pass SearchLink=false and execute the unit tests.
describe('Error Msg', () => {
it('styled component', () => {
const output = mount(<DisplayErr text="hello world" SearchLink=false/>)
expect(output.find(Link).props().to).toEqual('/search');
});
Let me know if you are facing the same issue.

How to simulate a click on a Font Awesome Icon using Jest?

I'm testing through Jest and am trying to test the click on a Font Awesome Icon. I've tried different ways to find the 'node', but I get the error that "Method “simulate” is meant to be run on 1 node. 0 found instead." Any insight would be helpful.
The error I get when I try different inputs to component.find() is: Method “simulate” is meant to be run on 1 node. 0 found instead.
StringEditor
const clearInput = () => {
onRemove()
}
render (
...
<FontAwesomeIcon icon={['fal', 'times-circle']} className="clear-button"
onClick={clearInput} /> : null`
)
onRemove is a callback function.
it('should call clearInput thus onRemove', () =>{
const onRemove= jest.fn()
const component = mount(<StringEditor {...defaultProps} onRemove={onRemove} />)
component.find('<dont know what to put>').simulate('click')
expect(saveValueFn).toBeCalled()
})
Try this:
it('should call clearInput thus onRemove', () =>{
const onRemove= jest.fn()
const component = mount(<StringEditor {...defaultProps} onRemove={onRemove} />)
component.find({ className: "clear-button" }).simulate('click');
expect(clearInput).toHaveBeenCalled();
})
You can use the Object Property Selector: https://airbnb.io/enzyme/docs/api/selector.html#4-object-property-selector
Or a React Component Constructor: https://airbnb.io/enzyme/docs/api/selector.html#2-a-react-component-constructor

Jest Invariant Violation

Simple use of react hooks in beta do not work when using jest and result in an error of
Invariant Violation: Hooks can only be called inside the body of a function component.
Despite much looking around I do not see working examples of Jest with react hooks. Yes I know it is beta but let us flag it now.
https://github.com/ghinks/jest-react-hook-issue.git
const MyDiv = () => {
const [count, setCount] = useState(0)
const clickHandler = () => { setCount(count + 1);
console.log(`clicked ${count}`) }
return (
<div onClick={clickHandler}>
ClickMe {count}
</div>
)
}
even simple tests
import { MyDiv } from './App';
describe('Test Component using hooks', () => {
test('MyDiv', () => {
const div = MyDiv();
expect(div).toMatchSnapshot();
})
});
will fail with the invariant error.
I would expect this to actually work.
looks like simple change to
describe('Test Component using hooks', () => {
test('MyDiv', () => {
expect(<MyDiv/>).toMatchSnapshot();
})
});
resolves this
The problem is what the error says. Function components aren't supposed to be called directly.
It should be as the reference shows:
import renderer from 'react-test-renderer';
...
const myDiv = renderer.create(<MyDiv/>).toJSON();
expect(myDiv).toMatchSnapshot();

how to change jest mock function return value in each test?

I have a mock module like this in my component test file
jest.mock('../../../magic/index', () => ({
navigationEnabled: () => true,
guidanceEnabled: () => true
}));
these functions will be called in render function of my component to hide and show some specific feature.
I want to take a snapshot on different combinations of the return value of those mock functions.
for suppose I have a test case like this
it('RowListItem should not render navigation and guidance options', () => {
const wrapper = shallow(
<RowListItem type="regularList" {...props} />
);
expect(enzymeToJson(wrapper)).toMatchSnapshot();
});
to run this test case I want to change the mock module functions return values to false like this dynamically
jest.mock('../../../magic/index', () => ({
navigationEnabled: () => false,
guidanceEnabled: () => false
}));
because i am importing RowListItem component already once so my mock module wont re import again. so it wont change. how can i solve this ?
You can mock the module so it returns spies and import it into your test:
import {navigationEnabled, guidanceEnabled} from '../../../magic/index'
jest.mock('../../../magic/index', () => ({
navigationEnabled: jest.fn(),
guidanceEnabled: jest.fn()
}));
Then later on you can change the actual implementation using mockImplementation
navigationEnabled.mockImplementation(()=> true)
//or
navigationEnabled.mockReturnValueOnce(true);
and in the next test
navigationEnabled.mockImplementation(()=> false)
//or
navigationEnabled.mockReturnValueOnce(false);
what you want to do is
import { navigationEnabled, guidanceEnabled } from '../../../magic/index';
jest.mock('../../../magic/index', () => ({
navigationEnabled: jest.fn(),
guidanceEnabled: jest.fn()
}));
describe('test suite', () => {
it('every test', () => {
navigationEnabled.mockReturnValueOnce(value);
guidanceEnabled.mockReturnValueOnce(value);
});
});
you can look more about these functions here =>https://facebook.github.io/jest/docs/mock-functions.html#mock-return-values
I had a hard time getting the accepted answers to work - my equivalents of navigationEnabled and guidanceEnabled were undefined when I tried to call mockReturnValueOnce on them.
Here's what I had to do:
In ../../../magic/__mocks__/index.js:
export const navigationEnabled = jest.fn();
export const guidanceEnabled = jest.fn();
in my index.test.js file:
jest.mock('../../../magic/index');
import { navigationEnabled, guidanceEnabled } from '../../../magic/index';
import { functionThatReturnsValueOfNavigationEnabled } from 'moduleToTest';
it('is able to mock', () => {
navigationEnabled.mockReturnValueOnce(true);
guidanceEnabled.mockReturnValueOnce(true);
expect(functionThatReturnsValueOfNavigationEnabled()).toBe(true);
});

Resources