I am new to unit testing and trying to write test cases for checking the "text" dropdown options.
my code:
const options = [
{
key: 'Select',
text: 'value1',
},
<Dropdown
placeholder="dropdown value"
options={options[0]}
disabled={true}
className="style"
/>
my test file is:
let wrapper = shallow(<App />)
it('selected option text', () => {
const dropdown= shallow(<Dropdown options={options[0]} />)
const value= dropdown.find(Dropdown);
expect(value.children()).toEqual('value1');
How can I pass the options text into children? or is there any better way to do?
Related
I'm using Semantic UI in React, and I have two dropdown forms. The first dropdown has options Yes and No, and the second dropdown has the options A and B. If the first form has the option "Yes" selected (or if it is cleared), then I want the second dropdown to be cleared and disabled.
Currently, I have it such that the second dropdown is disabled as described, but I cannot figure out how to also clear the selected option (if there is one). I cannot do it in the same way that I disabled the dropdown (by saving a state variable), because Dropdown has the property clearable, not cleared.
Alternatively, could I set the second dropdown to some other third option C that is only set when it is disabled (and not accessible as an option)?
I've put below a Minimum Reproducible Example that demonstrates the disabling, but obviously not the clearing.
Thanks!
import React, { useState } from 'react';
import { Dropdown, Form} from "semantic-ui-react"
const firstDropdownOptions= [
{
key: 'Yes',
text: 'Yes',
value: 'Yes',
},
{
key: 'No',
text: 'No',
value: 'No',
},
]
const secondDropdownOptions= [
{
key: 'A',
text: 'A',
value: 'A',
},
{
key: 'B',
text: 'B',
value: 'B',
},
]
export const InputForm = () => {
const [firstVal, setFirstVal] = useState('')
const [secondVal, setSecondVal] = useState('')
const [condition, setCondition] = useState(false)
return (
<Form>
<Dropdown
placeholder='First Value'
selection
clearable
options={firstDropdownOptions}
onChange={(_, data) => {setFirstVal(data.value)};
if(data.value=="No"){setCondition(true)}
else{setCondition(false)};
}
/>
<Dropdown
placeholder='Second Value'
selection
clearable
disabled={condition}
options={secondDropdownOptions}
onChange={(_, data) => setSecondVal(data.value)}
/>
</Form>
)}
Dropdown should have value prop. But when clearing existing value in the second Dropdown, make sure to follow this instruction: https://github.com/Semantic-Org/Semantic-UI-React/issues/3625#issuecomment-654199235
Am writing some unit testing, I have a component with meta info set using Vue-meta
My Component looks like this.
export default {
...
metaInfo () {
const expertName = this.getBlogInfo.blog.author.trim()
const fullName = expertName ? `${expertName.first_name} ${expertName.last_name}` : 'Cowsoko'
return {
title: `Dairynomics - Blog post from ${fullName}`,
meta: [
{
vmid: 'og:description',
name: 'og:description',
content: this.description
},
{
vmid: 'og:image',
name: 'og:image',
content: this.getBlogInfo.blog.photo
}
]
}
}
...
There's an issue on their github repo which says you need to create a local Vue instance.
You can read about local Vue instances in the vue-test-utils docs. It allows you to add components, mixins and install plugins without polluting the global Vue class, i.e. add in the vue-meta properties for this test only.
import { shallowMount, createLocalVue } from '#vue/test-utils'
import Component from './Component.vue'
import VueMeta from 'vue-meta'
let localVue = createLocalVue();
localVue.use(VueMeta);
describe('Component.vue', function() {
// Set up the wrapper
const wrapper = shallowMount(Component)
it('has a getTitle() method that returns the page title', () => {
expect(wrapper.vm.getTitle()).toBe(title)
})
it('has its meta title correctly set', () => {
expect(wrapper.vm.$meta().refresh().metaInfo.title).toBe('some title')
})
})
You can insert your meta data normally in each component.
If your pages are dynamic and if you want any dynamic SEO or meta tags you can use vue-headful.
Like this
<vue-headful
title="Title from vue-headful"
description="Description from vue-headful"
/>
In vue-headful you can write all the meta tags.
I want to unit test with Jest and Enzyme if my <Text /> tag correctly receives props.header as text.
Usually I was able to test the content of the <Text /> tag like this:
it("should render a label", () => {
expect(wrapper.find(Text).contains("submit")).toBe(true);
});
But as soon as I pass an object this is no longer possible. Let me show you:
const createTestProps = props => ({
header: SOME_CONSTANT,
...props
});
...
let wrapper;
let props;
beforeEach(() => {
props = createTestProps();
wrapper = shallow(<MyList {...props} loaded={false} />);
});
it("should render a header", () => {
expect(wrapper.find(Text).contains(props.header)).toBe(true);
});
This fails with the following error message:
● MyList › rendering › still loading › should render a header
expect(received).toBe(expected) // Object.is equality
Expected: true
Received: false
How could I test this using Jest and Enzyme?
Edit
I found out that it has something to do passing a constant to the props. If I hardcode the value of props like this:
const createTestProps = props => ({
header: "Some hardcoded value",
...props
});
The test also passes. Is there a way to make this work even with a constant?
I have this React functional UI only component, which has two props passed in, the second being a function that is passed from its parent component. The onClick calls 'delegates' to a function in the parent container component, this parent method is then responsible for dispatching to a redux store.
import React, {Component} from 'react';
import PropTypes from 'prop-types';
const BotShowUI = ({ bot, onClick }) => {
return(
<div id={bot.id} onClick={onClick}>
{bot.id} : {bot.text}
</div>
)
}
BotShowUI.propTypes = {
bot: PropTypes.object.isRequired,
onClick: PropTypes.func.isRequired
};
export default BotShowUI;
My test spec is, which uses Jasmine
import React, {Component} from 'react';
import { mount } from 'enzyme';
import BotShowUI from '../botShowUI';
function onClickFunction(){};
describe('botShowUI', () => {
const bot = {id: 1, isDone: false, text: 'bot 123'};
const expectedDivText = '1 : bot 123';
const wrapper = mount(<BotShowUI bot={bot} onClick={onClickFunction} />);
it(' div has been rendered ', () => {
expect(wrapper.find('div').first()).not.toBe(null);
});
it(' div displays the correct bot text ', () => {
expect(wrapper.find('div').first().text()).toEqual(expectedDivText)
});
it(' div click event fired ', () => {
wrapper.simulate('click');
expect(wrapper.state('onClick')).toBe(true);
});
});
This last assertion fails with
Chrome 57.0.2987 (Windows 10 0.0.0) botShowUI div click event fired FAILED
TypeError: Cannot read property 'onClick' of null
at ReactWrapper.state (webpack:///~/enzyme/build/ReactWrapper.js:825:24 <- tests.webpack.js:26303:25)
at Object.<anonymous> (webpack:///app/react/components/bots/_tests/botShowUI.spec.js:25:23 <- tests.webpack.js:25415:25)
wrapper.simulate('click'); works, but the next line fails
What is the correct way to assert that the click was fired ?
Do I have to drop into wrapper's props/children instead of using state ?
I'm not trying to test the parent container in any way, the two are isolated.
This test is only concerned with this UI component.
First thing is that onClick isn't on state, but on props, so you will have to access it by doing wrapper.props('onClick').
Secondly, to test whether onClick has been handled or not is to use a spy, rather than an empty function. If you do not want to use spy, you can still do that, but not the way you have done. If you are interested, I can post some pseudo-code for that too. But coming back to using spies, you can use a spy as the onClick prop. Below is the code for that. I have hand-written it, so please check for any syntax error, but you should get the idea on what needs to be done.
it('should call the onClick handler on click', () => {
const onClickFunction = sinon.spy()
wrapper = mount(<BotShowUI bot={bot} onClick={onClickFunction} />)
wrapper.simulate('click');
expect(onClickFunction).toHaveBeenCalled();
})
Based on Abhishek's answer here's my solution for Jasmine
it(' div click event fired ', () => {
let onClickFunction_spy = jasmine.createSpy('onClickFunction');
const wrapper = mount(<BotShowUI bot={bot} onClick={onClickFunction_spy} />);
wrapper.simulate('click');
expect(onClickFunction_spy).toHaveBeenCalled();
});
Hope this helps anyone.
I've recently started learning angular2, and I thought I'd try and write a combobox component similar to select2. Here's a simplified version of the component:
#Component({
selector: 'combobox',
template: `
<div class="combobox-wrapper">
<input type="text"></input>
<button class="toggle-button"></button>
</div>
<div *ngIf="isDropdownOpen" class="dropdown">
<div *ngFor="let option of options; let index = index;"
class="option"
[class.focused]="focusedIndex==index">
{{option.label}}
</div>
</div>
`
})
export class ComboboxComponent {
#Input() options: any[] = [];
isDropdownOpen: boolean = false;
focusedIndex: number = 0;
}
I'm struggling when it comes to writing unit tests involving user interaction. For example, I want the user to be able to navigate the list of options by using the up and down keys on the keyboard. The way I see it, I have two options.
Option 1:
describe('when the dropdown is open and the user presses the "UP" key', () => {
it('should focus the first available preceeding option', () => {
const button = fixture.debugElement.query(By.css('.toggle-button'));
const input = fixture.debugElement.query(By.css('input'));
button.triggerEventHandler('mousedown', {});
input.triggerEventHandler('keydown', { key: 'ArrowDown' });
input.triggerEventHandler('keydown', { key: 'ArrowDown' });
input.triggerEventHandler('keydown', { key: 'ArrowUp' });
fixture.detectChanges();
const options = fixture.debugElement.queryAll(By.css('.option'));
expect(options[1].nativeElement.className).toContain('focused');
});
});
Option 2:
describe('when the dropdown is open and the user presses the "UP" key', () => {
it('should focus the first available preceeding option', () => {
const combobox = fixture.componentInstance;
combobox.isDropdownOpen = true;
combobox.focusedIndex = 2;
input.triggerEventHandler('keydown', { key: 'ArrowUp' });
fixture.detectChanges();
expect(combobox.focusedIndex).toBe(1);
});
});
Neither option feels right. In the first case I'm making assumptions about behaviour that is not part of the test itself - namely that clicking the "toggle" button will open the dropdown, and that pressing the "ArrowDown" key will focus the next option on the list.
In the second case I'm accessing properties that are not part of the component's public interface (#Inputs and #Outputs), and the test itself requires detailed knowledge about the actual implementation.
How should I approach this?