fireEvent.click with parameters - react-testing-library

I have a radio button that when I click it calls a function with two parameters in the function (value and step), and when I make a test with testing librairy I would like that when I simulate the click of the button I return the two parameters.
Button
<Form.Check
inline
label={'form.email'}
name="media"
value={`LETTER`}
type="radio"
data-testid="EMAIL"
onClick={(e) => {
const target = e.target as HTMLTextAreaElement;
changeMedia(target.value, data);
}}
/>
Function ChangeMedia
const changeMedia = (value: any, step: any) => {
step.definition?.steps
.filter((obj: any) => obj.media.includes(value))
.map((item: any) => {
if (value === 'EMAIL') {
item.media = 'LETTER';
return item;
} else if (value === 'LETTER') {
item.media = 'EMAIL';
return item;
}
return item;
});
return data;
};
Objet Step
const step = {
definition: {
steps: [
{
document_model: 'template_circularization',
email_model: 'email_circularization',
label: {
EN: 'Circularization',
FR: 'Circularisation',
},
media: 'LETTER',
name: 'mail_circularization',
onDemandOnly: true,
},
],
},
};
Test
const radio = screen.getByTestId('EMAIL');
fireEvent.click(radio, { target: { value: 'EMAIL, step: step } });
when I do a console.log of value and step I get this :
value EMAIL
step {}
what would be the solution to retrieve the step object via firevent.click ?

Related

AgGrid - How can i have radio button filter instead of checkbox?

I have a custom filter values such as:
filterParams: {
values: ['Admin', 'Proje Yöneticisi', 'Muhasebe'],
defaultToNothingSelected: true,
suppressSelectAll: true
},
However, I can choose multiple values like this. But I don't want to do that, I want to choose only one value instead of multiple choices.
Is there a way to convert this checkbox filter into a radio filter?
Thanks.
You can make a custom filter and there is a video on it: https://www.youtube.com/watch?v=yO3_nTyDv6o
Create a component like this, i am dynamically looking up the options to be displayed based on the extra column parameters supplied in the column def (e.g. thats where props.meta comes in)
import { Button, Radio, RadioGroup, Stack } from "#chakra-ui/react";
import { IFilterParams } from "ag-grid-community";
import React from "react";
import { IRegistryDataColumn } from "../../../../models/RegistryDataColumn";
interface IProps extends IFilterParams {
meta?: IRegistryDataColumn;
}
interface IOption {
value: string;
label: string;
}
export const FilterRadio = React.forwardRef((props: IProps, ref) => {
const [radioOptions, setRadioOptions] = React.useState<IOption[]>([]);
const [filterState, setFilterState] = React.useState<string>();
const handleClear = () => {
setFilterState(undefined);
};
// expose AG Grid Filter Lifecycle callbacks
React.useImperativeHandle(ref, () => {
return {
isFilterActive() {
return filterState !== undefined;
},
doesFilterPass(params) {
const isPass =
params.data[props.colDef.field as string] === filterState;
return isPass;
},
getModel() {},
setModel() {},
};
});
React.useEffect(() => {
props.filterChangedCallback();
}, [filterState]);
React.useEffect(() => {
const radioOptionsUpdate: IOption[] = [];
if (props.meta?.radio_options) {
Object.entries(props.meta.radio_options).forEach(([key, value]) => {
radioOptionsUpdate.push({ value: value.value, label: value.label });
});
}
setRadioOptions(radioOptionsUpdate);
}, [props.meta?.radio_options]);
return (
<Stack p={4} spacing={6} style={{ display: "inline-block" }}>
<Button size="sm" onClick={handleClear}>
Clear filter
</Button>
<RadioGroup onChange={setFilterState} value={filterState}>
<Stack spacing={4}>
{radioOptions.map((option) => (
<Radio key={option.value} value={option.value}>
{option.label}
</Radio>
))}
</Stack>
</RadioGroup>
</Stack>
);
});
And then include it in the column definition:
newCol.filter = FilterRadio;

How to get selected and creatable value in AutoComplete (Material UI). I bind Data from onChange method to setState but this is not what I expected

I want to get AutoComplete onChange data. I got data from onChange((e,value) => console.log(value).
But how to put data on State .
This AutoComplete component behaviour is (Creatable and selectable) . I got all data on onChange but on in the state, If I set the data on State , selectOnFocus is not working.
How to get rid of that?
Thank you
`
<Autocomplete
multiple
limitTags={5}
onChange={(event, newValue) => {
setToEmails(newValue);
}}
filterOptions={(options, params) => {
const filtered = filter(options, params);
if (params.inputValue !== "") {
filtered.push({
inputValue: params.inputValue,
label: `Add "${params.inputValue}"`,
value: nanoid(7),
});
}
return filtered;
}}
selectOnFocus
blurOnSelect
clearOnBlur
handleHomeEndKeys
id="free-solo-with-text-demo"
options={toBlockers}
getOptionLabel={(option) => {
if (typeof option === "string") {
return option;
}
if (option.inputValue) {
return option.inputValue;
}
return option.label;
}}
renderOption={(option) => option.label}
freeSolo
renderInput={(params) => (
<TextField {...params} label="Blockers" variant="outlined" />
)}
/>
`
If I use this , Selectable is not working.
Later on I got solved by myself . This took about 3 days ,
here is full example of Creatable with selectable with formData thing.
const [toEmails, setToEmails] = useState([]);
//if you want to post this data on formData , you have structured this way
const appendedObject = [
{ label: "_creative", value: "node_process_Lh1L8RsafJbUas" },
{ label: "Azim__bro", value: "node_process_LhL1s8RaafJbUas" },
];
const finalBlockers = [...appendedObject, ...toEmails];
formData.append("attachmentList", []);
console.log({ toEmails, finalBlockers });
if (finalBlockers) {
for (const blocker of finalBlockers) {
console.log({ blocker });
formData.append("blockers", JSON.stringify(blocker));
}
}
<Autocomplete
multiple
limitTags={5}
getOptionSelected={(option, value) => {
const optionTitle =
typeof option === "string" ? option : option.value;
const valueTitle =
typeof value === "string" ? value : value.value;
return optionTitle === valueTitle;
}}
onChange={(event, newValue) => {
if (Array.isArray(newValue)) {
const updatedArrayValue = newValue.filter((e) =>
typeof e === "string" ? e.trim() : e
);
const newArrayValue = [...updatedArrayValue];
const updatedArray = newArrayValue.map((item) => {
if (typeof item === "string") {
const newItem = {};
newItem.label = item;
newItem.value = nanoid(12);
newItem.type = "created";
return newItem;
}
return item;
});
setToEmails(updatedArray);
}
}}
filterOptions={(options, params) => {
const filtered = filter(options, params);
if (params.inputValue !== "") {
filtered.push({
inputValue: params.inputValue,
title: `Add "${params.inputValue}"`,
value: nanoid(12),
type: "created",
});
}
return filtered;
}}
selectOnFocus
clearOnBlur
handleHomeEndKeys
id="free-solo-with-text-demo"
options={toBlockers}
filterSelectedOptions
getOptionLabel={(option) => {
// Value selected with enter, right from the input
if (typeof option === "string") {
return option;
}
// Add "xxx" option created dynamically
if (option.inputValue) {
return option.inputValue;
}
// Regular option
return option.label;
}}
renderOption={(option) => option.label}
freeSolo
renderInput={(params) => (
<TextField {...params} label="Blockers" variant="outlined" />
)}
/>

Redux Toolkit - action from one slice to be caught in another slice

There's an action (addOrder) in an orderSlice
orderSlice.js
import { createSlice } from '#reduxjs/toolkit';
const initialState = {
orders: []
};
const ordersSlice = createSlice({
name: 'orders',
initialState,
reducers: {
addOrder: {
reducer: (state, action) => {
state.orders.push(action.payload)
},
prepare: (orderItems, orderTotal) => {
const orderDate = new Date().toDateString();
return { payload: { orderDate, orderItems: orderItems, orderTotal: orderTotal }}
}
}
}
})
export const { addOrder } = ordersSlice.actions;
export default ordersSlice.reducer;
I'd like it to also affect the state in another slice (cartSlice). Once the 'addOrder' is fired, it should also bring the cartReducer to its initial state. Some googling suggested that I should use extrareducers for that but I'm really not getting its syntax. See below (not valid code in extrareducers)
cartSlice
import { createSlice } from '#reduxjs/toolkit';
import { addOrder } from './ordersSlice';
const initialState = {
items: {},
totalAmount: 0
};
const cartSlice = createSlice({
name: 'cart',
initialState: initialState,
reducers: {
addToCart: (state, action) => {
// p = product to be added or amended
const p = action.payload;
if (state.items[p.id]) {
// already exists
state.items[p.id].quantity += 1;
state.items[p.id].sum += p.price;
state.totalAmount += p.price;
} else {
state.items[p.id] = { price: p.price, quantity: 1, title: p.title, sum: p.price};
state.totalAmount += p.price;
}
},
removeFromCart: (state, action) => {
console.log('remove from cart');
console.log(action.payload);
const currentQuantity = state.items[action.payload].quantity;
console.log(currentQuantity);
if (currentQuantity > 1) {
state.items[action.payload].quantity -= 1;
state.items[action.payload].sum -= state.items[action.payload].price;
state.totalAmount -= state.items[action.payload].price;
} else {
state.totalAmount -= state.items[action.payload].price;
delete state.items[action.payload];
}
}
},
extraReducers: (builder) => {
builder
.addCase(addOrder(state) => {
return initialState;
})
}
});
export const { addToCart, removeFromCart } = cartSlice.actions;
export default cartSlice.reducer;
You're almost there! The builder.addCase function takes two arguments. The first is the action creator and the second is the case reducer. So you need a comma after addOrder.
extraReducers: (builder) => {
builder.addCase(addOrder, (state) => {
return initialState;
});
}

i want to do a dynamic form with v-if

I want to display an additional input if the person clicks yes and clicks on nothing
i try to do that with v-if but i the value never change
this is the entire page in vuejs maybe i need to do a method, i already try without quote and with, i to set value like club = 1 but didn't work to.
I'm not sure if my v-bind is good too
<el-form-item label="Possédez vous un club ?">
<el-radio-group v-model="ruleForm.club">
<el-radio label="Oui" v-bind:value="true"></el-radio>
<el-radio label="Non" v-bind:value="false"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="'ruleForm.club' == true" label="Nom du club" prop="nClub">
<el-input v-model="ruleForm.nClub" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" #click="submitForm('ruleForm')">Submit</el-button>
<el-button #click="resetForm('ruleForm')">Reset</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
data () {
var validatePseudo = (rule, value, callback) => {
if (value === '' || value !== 'coach') {
callback(new Error('Please input the pseudo'))
} else {
callback()
}
}
var validatePass = (rule, value, callback) => {
if (value === '' || value !== 'password') {
callback(new Error('Please input the password'))
} else {
callback()
}
}
return {
ruleForm: {
nom: '',
prenom: '',
pseudo: '',
email: '',
pass: '',
statue: '',
club: '',
nClub: ''
},
rules: {
pseudo: [
{ validator: validatePseudo, trigger: 'blur' }
],
pass: [
{ validator: validatePass, trigger: 'blur' }
]
}
}
},
methods: {
submitForm (formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$router.push({
name: '/'
})
} else {
console.log('error submit!!')
return false
}
})
},
resetForm (formName) {
this.$refs[formName].resetFields()
},
}
}
</script>
I do not really understand your question, but from what I can tell you would like to add an inputfield if a user selects a certain radio button using v-if. I've recreated this in a jsfiddle. Is this wat your looking for?
Link: https://jsfiddle.net/Mertakus/8wx4h7up/3/

How to implement an ag-grid custom floating filter with material-ui withStyles HoC?

Created an ag-grid custom floating filter with validation and need to style the filter when the validation fails with material-ui themed class using withStyles higher order component (HoC). However, when you wrap the custom floating filter with HoC onParentModelChanged doesn't get called at all.
Used hard-coded style to set the element style property but this is not allowed in the themed project using #material-ui/core v1.4.0.
Below is the custom floating filter that I created with validation and hard-coded style.
import { PropTypes } from 'prop-types';
import styles from './styles';
const DEFAULT_MIN_CHARS = 3;
const ENTER_KEY = 13;
export class CustomFloatingFilter extends Component {
constructor(props) {
super(props);
this.state = {
currentValue: '',
minChars: props.minChars ? props.minChars : DEFAULT_MIN_CHARS,
invalidFilter: false,
styles: styles()
};
this.keyPressed = this.keyPressed.bind(this);
this.valueChanged = this.valueChanged.bind(this);
this.onParentModelChanged = this.onParentModelChanged.bind(this);
this.onFloatingFilterChanged = change => {
const { minChars } = this.state;
if(change && change.model && (!change.model.filter || change.model.filter.length >= minChars)) {
return props.onFloatingFilterChanged(change);
}
return false;
};
}
keyPressed(event) {
this.setState(
{ enterPressed: event.which === ENTER_KEY },
() => {
const { enterPressed } = this.state;
if(enterPressed) { //update filter only when enter. valueChanged will handle all other cases
this.onFloatingFilterChanged(this.buildChanged());
}
}
);
}
valueChanged(event) {
const { minChars } = this.state;
this.setState(
{
currentValue: event.target.value,
invalidFilter: !!event.target.value && event.target.value.length < minChars
},
() => {
this.onFloatingFilterChanged(this.buildChanged());
}
);
}
onParentModelChanged(parentModel) {
this.setState({ currentValue: parentModel ? parentModel.filter : '' });
}
buildChanged() {
const { currentValue, enterPressed, invalidFilter } = this.state;
return {
model: {
filterType: 'text',
type: 'equals',
filter: currentValue
},
apply: !invalidFilter && (enterPressed || currentValue === '') //for applyButton:true case
};
}
render() {
const { currentValue, invalidFilter, styles } = this.state;
return (
<div style={invalidFilter ? styles.invalid : {} //eslint-disable-line
//withStyles HoC doesn't work with ag-grid floating filter component
}
>
<input className='ag-floating-filter-input' onKeyPress={this.keyPressed} onChange={this.valueChanged} value={currentValue} />
</div>
);
}
}
CustomFloatingFilter.propTypes = {
minChars: PropTypes.number,
onFloatingFilterChanged: PropTypes.func
};
export default CustomFloatingFilter;