How does one use the semantic-ui-react Label OnRemove handler /removeIcon property? - semantic-ui-react

I noticed that the semantic-ui-react Label has an OnRemove handler as well as a removeIcon property. I am wondering how this is supposed to be used with other controls, as it does not seem to be well documented. For example, how would I make use of this with an Input or Form.Input?

Here is an usage example:
onRemove = (event, data) => {
console.log("onRemove event");
}
render() {
return (
<Label color='teal' content='Label content' removeIcon='delete'
onRemove={this.onRemove} />
);
}

Related

How to check if conditional rendering is shown after selecting an option from a select list with React Testing Library?

I'm trying to test my component that has the following conditional rendering:
const MyComponent = () => {
const [isVisible, setIsVisible] = (false);
if(selectedOption == 'optionOne')
setIsVisible(true);
else
setIsVisible(false);
return (
<div>
<Select data-testid="select1" selectedOption={selectedOption} />
{isVisible ? <Select data-testid="select2" selectedOption={anotherSelectedOption} /> : null }
</div>
)}
If selectedOption in select1 is 'optionOne', then select2 shows up.
Here is how I am testing it:
describe('Testing', () => {
let container: ElementWrapper<HTMLElement>;
const testState = {
userChoice1: {
selectedOption: ['optionOne'],
},
userChoice2: {
selectedOption: ['test1', 'test2'],
},
} as AppState;
beforeEach(() => {
container = render(<MyComponent/>, testState);
});
it('should show select2 if optionOne is selected', async () => {
const { getByTestId, getAllByTestId } = render(<MyComponent/>);
expect(container.find('span').getElement().textContent).toBe("optionOne"); // this successfully finds select1 with optionOne selected, all good
await screen.findAllByTestId('select2')
expect(screen.getAllByTestId('select2')).toBeInTheDocument();
});
In the testing above, as select1 has optionOne selected, I expect to select2 to show up. However, I am getting an error Unable to find an element by: [data-testid="select2"]. It also returns the whole HTML body, where I see select1 element with optionOne selected, but no select2 at all as it seems to still be hidden.
What am I missing here? How can I unhide select2 within the unit test?

React Semantic UI - Modal without trigger?

Is it possible to use a Modal without a trigger? I will open and close it via state.
For example, I want to use onClick on an input field(with a file name) to open the modal with a file chooser and then edit the name of the choosen file in the input field. All this in a nested modal...
Looks much simpler if I will have both modals in a parent component without the triggers, and I will display/hide them via open={true/false}
Thanks
Yes it is. Don't set the prop trigger (it is not required) and just provide the open value from state/props.
class container extends Component {
state = {
isParentOpen: false,
isChildOpen: false
}
handleClick = () => {
this.setState({
isParentOpen: !this.state.isOpen
});
}
handleFocus = () => {
this.setState({
isChildOpen: true
});
}
render() {
return (
<div>
<Modal
open={this.state.isParentOpen}
size="large"
>
...
<Input onFocus={this.handleFocus} />
</Modal>
<Modal
open={this.state.isChildOpen}
size="small"
>
...
</Modal>
<Button onClick={this.handleClick} />
</div>
);
}
}
(You can nest Modal if you want to)
Pass a prop to the modal component and fire handleOpen according to the prop on ComponentDidMount. This will allow the modal to be closed.
class ModalContainer extends Component {
componentDidMount() {
const { startOpen } = this.props;
if (startOpen) {
this.handleOpen();
}
}
handleOpen = () => this.setState({ modalOpen: true });
handleClose = () => this.setState({ modalOpen: false });
render() {
return (
<Modal open={this.state.modalOpen} onClose={this.handleClose} />
)
}

How to mock e.preventDefault in react component's child

Hy, I don't know how to mock an inline function in React component's child
My stack: sinon, chai, enzyme;
Component usage:
<ListItem onClick={() => someFn()} />
Component's render:
render() {
return (
<li>
<a href="#" onClick={e => {
e.preventDefault();
this.props.onClick();
}}
> whatever </a>
</li>
);
}
Here we have onClick function that calls e.preventDefault(). How to tell to <a href>(link) to not to call e.preventDefault()? How can I mock an onClick?
Below is what I have tried in tests:
Shallow copy setup
function setup() {
const someFn = sinon.stub();
const component = shallow(
<ListItem
onClick={() => {
someFn();
}}
/>
);
return {
component: component,
actions: someFn,
link: component.find('a'),
listItem: component.find('li'),
}
}
And the test
it('simulates click events', () => {
const { link, actions } = setup();
link.simulate('click'); //Click on <a href>
expect(actions).to.have.property('callCount', 1); //will be fine if we remove e.preventDefault()
});
Test's output error:
TypeError: Cannot read property 'preventDefault' of undefined
Try this
link.simulate('click', {
preventDefault: () => {
}
});
test('simulates click events', () => {
const e = { stopPropagation: jest.fn() };
const component = shallow(<ListItem{...props} />);
const li = component.find('li').at(0).childAt(0)
li.props().onClick(e)
expect();
});
For those using Jest and #testing-library or react-testing-librarys fireEvent, you need to provide an initialised event object, otherwise the event can't be dispatched via your element.
One can then assert on e.preventDefault being called by assigning a property to that initialised event:
test('prevents default on click', () => {
const {getByText} = render(<MyComponent />);
const button = getByText(/click me/);
// initialise an event, and assign your own preventDefault
const clickEvent = new MouseEvent('click');
Object.assign(clickEvent, {preventDefault: jest.fn()});
fireEvent(button, clickEvent);
expect(clickEvent.preventDefault).toHaveBeenCalledTimes(1);
});
Similarly for stopPropagation.
Anton Karpenko's answer for Jest was useful.
Just to note that this is an issue only when using shallow enzyme renderer. In case of full DOM renderer mount, the event object contains the preventDefault method, therefore you don't have to mock it.
You can define an object with regarding function you will mock via some testing tool, for example look at Jest and Enzyme
describe('Form component', () => {
test('deos not reload page after submition', () => {
const wrapper = shallow(<TodosForm />)
// an object with some function
const event = { preventDefault: () => {} }
// mocks for this function
jest.spyOn(event, 'preventDefault')
wrapper.find('form').simulate('submit', event)
// how would you know that function is called
expect(event.preventDefault).toBeCalled()
})
})
I would suggest to create new object based on jest.fn() with
const event = Object.assign(jest.fn(), {preventDefault: () => {}})
then use it:
element.simulate('click', event);
I am using Web Components and this works for me -
const callback = jest.fn();
MouseEvent.prototype.stopPropagation = callback;
const element = createElement({});
element.shadowRoot.querySelector('ul').click();
expect(callback).toHaveBeenCalledTimes(1);

React how to test out react compoennt with setTimeout

I am run into this test problem, which i am not sure how to test component with settimeout. anyone have suggestion on how to test out the following component with settimeout? Many thanks
import React, { PropTypes, Component } from 'react';
import styles from '../../../css/notification.css';
export default class Notification extends Component {
static propTypes = {
tagMetaUpdate: PropTypes.shape({
submitUpdatedTagDataSuccessful: PropTypes.bool
}),
actions: PropTypes.shape({
resetUpdatedTagDataSuccessfulFlag: PropTypes.func
})
};
constructor(props) {
super(props);
this.state = {
showMessage: true
};
}
hideMessage(actions) {
this.timer = setTimeout(() => {
this.state.showMessage = false;
actions.resetUpdatedTagDataSuccessfulFlag();
this.forceUpdate();
}, 3000);
}
render() {
const { tagMetaUpdate, actions } = this.props;
const output = (tagMetaUpdate.submitUpdatedTagDataSuccessful && this.state.showMessage) ?
<div className={styles.notification}>Tag meta data successfully edited.</div> : null;
if (this.props.tagMetaUpdate.submitUpdatedTagDataSuccessful) {
this.hideMessage(actions); // HERE IS THE BIT BLOCKING ME
}else {
this.state.showMessage = true;
}
return <div>{output}</div>;
}
}
use sinnon Faking time will solve the problem
http://sinonjs.org/
scroll to Faking time
It is generally ill-advised to mutate the state directly. Try to use this.setState({}), and when you call setState, this.forceUpdate is unnecessary. React would update your component by itself.
Also, try to use the render method to only perform rendering. No mutating state and all that.
If you directly do this.setState({ showMessage: true }) in the render method, react would complain about it - that it's not allowed.
React provides a lifecycle hook methods called componentWillRecieveProps and componentWillUpdate. You can use them to check if the prop has changed and then do setState accordingly.
componentWillReceiveProps(nextProps){
if(!_.isEqual(nextProps, this.props) {
if(nextProps.tagMetaUpdate.submitUpdatedTagDataSuccessful){
this.setState({ showMessage: true })
this.timer = setTimeout(() => {
this.setState({ showMessage: false })
actions.resetUpdatedTagDataSuccessfulFlag()
}, 3000)
}
}
}
Note that:
by using setState in the setTimeout, I've eliminated the need to use forceUpdate()
i use lodash to do a check to see if the prop has changed from the previous render to the current one. React would re-render the component for one of these reasons:
if the prop changes
if the component's state updates
if one of its parents need to update for either of the two reasons.
So we do a check to see that the update is only happening because the prop has changed, and if it has, then do a setState to show the message and a set timeout to not show the message after 3 seconds.
These are just usage advices. Can you tell me more about the framework you use for unit testing. I might be able to help a bit if it's jest.

Ember.Instrumentation.subscribe: Trigger event from handlebars

In the init of my view I have setup the event listening as follows:
Ember.Instrumentation.subscribe("inlineEdit.makeBlue", {
before: function (name, timestamp, payload) {
alert(name, timestamp,payload);
},
after: function () {
}
});
From handlebars I would like to trigger the event with an action:
<a {{action inlineEdit.makeBlue on="mouseDown"}} class="btn ">Blue</a>
Unfortunately this does not trigger the above event listener. Can an instrumenation event be triggered from handlebars? If yes how?
At the moment isn't avaliable in the ember core, but it's possible to implement.
When you use the actions internally ember will use the Ember.ActionHandler#send method to dispatch these events. So you can reopen that class, and proxy the method, wrapping the invocation in a Ember.instrument:
Ember.ActionHandler.reopen({
send: function(actionName) {
var orininalArguments = arguments,
args = [].slice.call(arguments, 1),
result;
Ember.instrument('action.' + actionName, args, function() {
result = this._super.apply(this, orininalArguments);
}, this);
return result;
}
});
So you can subscribe:
// Specific action
Ember.Instrumentation.subscribe("action.inlineEdit.makeBlue", { ... })
I added the action prefix in the subscription, so you can take advantage of the instrumentation api, and listen all action events with:
// All actions
Ember.Instrumentation.subscribe("action", { ... })
Give a look in that fiddle to see this working http://jsfiddle.net/marciojunior/8P46f/
I hope it helps