simulate change not working with trim() enzyme - reactjs

I was using this test when I had a bug, so I used the trim function for resolve it, and the these test fail, tried in different ways but didn't found the solution
const generalWrapper = shallow(<AddVehiclesTable {...generalProps} />)
const generalInstance = generalWrapper.instance()
describe('onSearchChange', () => {
test('should change the "search" state', () => {
const theFilterValue = 'a new filter value'
generalWrapper.find('.filter-input').simulate('change', { target: { value: theFilterValue } })
const expectedState = Object.assign({}, generalInstance.state)
expectedState.searchValue = { 'target': { 'value': theFilterValue } }
expect(generalInstance.state).toEqual(expectedState)
expect(generalInstance.state.userInteractedWithComponent).toBe(true)
})
})
onSearchChange (searchValue) {
const value = searchValue.trim()
this.setState({ searchValue: value, userInteractedWithComponent: true })
}
Error message
TypeError: searchValue.trim is not a function
Any suggestions

Your function gets the Object as a parameter.
Expose field that you needed
I don't see the whole picture, but can guess that you need something like
onSearchChange ({ target: { value: incomeValue } }) {
const value = incomeValue.trim()
this.setState({ searchValue: value, userInteractedWithComponent: true })
}

Related

I get undefined from state

I have problem, in the code below I'm trying to console.log only name of the playLists from state with console.log(this.state.playLists.name); I get undefined.
getPlaylist() {
spotifyApi.getUserPlaylists().then((response) => {
if (response.items) {
const items = response.items;
console.log(items);
const playListsId = items.map((obj) => {
const playList = {
name: obj.name,
id: obj.id,
};
return playList;
});
console.log(playListsId);
this.setState({
playLists: playListsId,
});
}
console.log(this.state.playLists.name);
});
}
Since this.state.playLists is an array you cannot get name on it. you have to get the name of all elements in an array.
Try this in place of console.log(this.state.playLists.name);
this.state.platLists.map(playList => console.log(playList.name));

Jest: How to update a value of a mock function in an onChange method?

In the following code everything works except for the update of the value in the onChange method.
The expected way it should work is:
initial value is an empty string (✓ works)
when a change is made the value should be the value of the change (✗ does not work)
const mockSetFieldValue = jest.fn(() => '');
beforeAll(async () => {
field = {
name: 'password',
value: mockSetFieldValue(),
// ^^^ initial value is picked up, but not the change in onChange
onChange: (e) => {
console.log(e.target.value) // returns: foo123
mockSetFieldValue.mockReturnValue(() => e.target.value);
// ^^^ this does not update the value
},
};
tree = (
<>
<label htmlFor="password">Password</label>
<MyField field={field} />
</>
);
});
it('input accepts a value', () => {
const { getByLabelText } = render(tree);
const input = getByLabelText(/Password/i);
fireEvent.change(input, { target: { value: 'foo123' } });
expect(input.value).toBe('foo123');
});
How would it be possible to update the onChange method to change the value that is set in my component?
I've tried mockImplementationOnce and mockReturnValue. But they don't seem to work that way.
field.value is set once before all your tests using the current value of the mockSetFieldValue function, which returns the empty string. Changing the mockSetFieldValue function therefore has no effect.
You need to be able to set the field.value in onChange, which you could do like this:
onChange: (e) => {
field.value = e.target.value;
},
It is probably better to mock out the whole onChange function:
const mockOnChange= jest.fn();
beforeAll(async () => {
field = {
name: 'password',
value: '',
onChange: mockOnChange,
};
//...
});
Then in the test:
mockOnChange.mockImplementationOnce((e) => { field.value = e.target.value });
fireEvent.change(input, { target: { value: 'foo123' } });

How can I see state within a function? using hooks

I'm trying to update the uploadFiles state inside my updateFile function, when reloading the file, I'm rewriting this component in hooks, but inside the function the state is given as empty.
const [uploadedFiles, setUploadedFiles] = useState({
slides: [],
material: [],
});
const updateFile = useCallback(
(id, data) => {
const value = uploadedFiles.slides.map(uploadedFile => {
return id === uploadedFile.id
? { ...uploadedFile, ...data }
: uploadedFile;
});
console.log('value', value);
console.log('uploadedFilesOnFunction', uploadedFiles);
},
[uploadedFiles]
);
function processUpload(upFile, type) {
const data = new FormData();
data.append('file', upFile.file, upFile.name);
api
.post('dropbox', data, {
onUploadProgress: e => {
const progress = parseInt(Math.round((e.loaded * 100) / e.total), 10);
updateFile(upFile.id, {
progress,
});
},
})
.then(response => {
updateFile(upFile.id, {
uploaded: true,
id: response.data.id,
url: response.data.url,
type,
});
})
.catch(response => {
updateFile(upFile.id, {
error: true,
});
});
}
function handleUpload(files, type) {
const uploaded = files.map(file => ({
file,
id: uniqueId(),
name: file.name,
readableSize: filesize(file.size),
preview: URL.createObjectURL(file),
progress: 0,
uploaded: false,
error: false,
url: null,
type,
}));
setUploadedFiles({
slides: uploadedFiles.slides.concat(uploaded),
});
uploaded.forEach(e => processUpload(e, type));
}
console.log('slides', uploadedFiles);
I expected the state values to be viewed by the function. For me to manipulate and set the state.
There might be other issues, but one thing I've noticed is:
const [uploadedFiles, setUploadedFiles] = useState({
slides: [],
material: [],
});
// A setState CALL FROM THE useState HOOK REPLACES THE STATE WITH THE NEW VALUE
setUploadedFiles({
slides: uploadedFiles.slides.concat(uploaded),
});
From: https://reactjs.org/docs/hooks-state.html
State variables can hold objects and arrays just fine, so you can still group related data together. However, unlike this.setState in a class, updating a state variable always replaces it instead of merging it.
The setState from the useState hook doesn't merge the state. Because it can hold any type of value, not only objects, like we used to do with classes.
From your code you can see that you're erasing some property from state when you're updating like that.
Instead, you should use the functional form of the setState and access the current state prevState, like:
setUploadedFiles((prevState) => {
return({
...prevState,
slides: uploadedFiles.slides.concat(uploaded)
});
});
The updated updateFiles function:
const updateFile = (id, data) => {
setUploadedFiles(prevState => {
const newSlide = prevState.slides.map(slide => {
return id === slide.id ? { ...slide, ...data } : slide;
});
return {
...prevState,
slides: newSlide,
};
});
};

Unit test for a function calling another function using jest

I'm new to Jest and having some issues to write the unit test.
My function is calling another anonymous function with some parameters.
Could you please help me fix it?
const myFunctionToTest = (code, data) => (isValid, availableCodes, defaultValue) => {
if(isValid) {
const isAvailableCode = isEmpty(availableCodes) || includes(availableCodes, code);
return isAvailableCode ? get(data, 'originalQty') : defaultValue;
}
return defaultValue;
};
Here's the mock data:
Mock data:
code: 'AB'
data: { originalQty : 2 };
isValid: true;
availableCodes: ['BCD', 'AB'];
defaultValue: 0;
What I tried!
describe('myFunctionToTest', () => {
test('it should return originally assigned quantity', () => {
const result = myFunctionToTest('AB', { originalQty: 2 } , () => {true, ['BCD', 'AB'], 0});
expect(result).toEqual(2);
});
});
Ok, I got it.
This is what I tried!
describe('myFunctionToTest', () => {
test('it should return originally assigned quantity', () => {
const result = myFunctionToTest('AB', { originalQty: 2 });
expect(result(true, ['BCD', 'AB'], 0).toEqual(2);
});
});

how to set state in react componentDidMount with method?

code is like this:
componentDidMount() {
this.setState(({getPublicTodosLength}, props) => ({
getPublicTodosLength: () => this.getPublicTodosLengthForPagination() // no returned value
}));
}
getPublicTodosLengthForPagination = async () => { // get publicTodos length since we cannot get it declared on createPaginationContainer
const getPublicTodosLengthQueryText = `
query TodoListHomeQuery {# filename+Query
viewer {
publicTodos {
edges {
node {
id
}
}
}
}
}`
const getPublicTodosLengthQuery = { text: getPublicTodosLengthQueryText }
const result = await this.props.relay.environment._network.fetch(getPublicTodosLengthQuery, {})
return result.data.viewer.publicTodos.edges.length;
}
getPublicTodosLengthForPagination is not invoked and the returned value is not assigned.Also, When i invoke it right away e.g. without () => it's assigned value is a promise? I am expecting int/number, the return value of edges.length. help?
The returned value is not assigned because you are not invoking the function rather assigning it.
componentDidMount() {
this.setState(({getPublicTodosLength}, props) => ({
getPublicTodosLength: this.getPublicTodosLengthForPagination()
}));
}
I'm not sure why you're setting state like that, maybe you could help explain what you're doing. In the meantime shouldn't it be written like this:
componentDidMount() {
this.setState({
getPublicTodosLength: await this.getPublicTodosLengthForPagination() // no returned value
});
}
getPublicTodosLengthForPagination = async () => { // get publicTodos length since we cannot get it declared on createPaginationContainer
const getPublicTodosLengthQueryText = `
query TodoListHomeQuery {# filename+Query
viewer {
publicTodos {
edges {
node {
id
}
}
}
}
}`
const getPublicTodosLengthQuery = { text: getPublicTodosLengthQueryText }
const result = await this.props.relay.environment._network.fetch(getPublicTodosLengthQuery, {})
return result.data.viewer.publicTodos.edges.length;
}

Resources