Asserting set of arrays. But 1st set of array only compare the first one - arrays

Hi i have this code and i want to assert the emailDataVal to equal to obfuscateEmailText but the emailDataVal only comparing the first result in it's array. It goes like this
Expected result:
emailDataVal = [email1, email2, email3, email4]
obfuscateEmailText = [email1, email2, email3, email4]
Actual result:
emailDataVal = [email1, email1, email1, email1]
obfuscateEmailText = [email1, email2, email3, email4]
it('test', () => {
cy.visit('/landing');
cy.get('.mailto-obfuscated-email').each((emailVal) => {
const emailDataVal = emailVal.data('value')
cy.log(emailDataVal)
cy.get('.amailto-obfuscated-email').each((emailContent) => {
const emailContentText = emailContent.text()
const obfuscateEmailText = emailContentText
.replaceAll('.', '(dotted)')
.replaceAll('#', '(at)')
cy.log(obfuscateEmailText)
// ASSERTION
expect(emailDataVal).to.deep.equal(obfuscateEmailText)
});
});
});
});

You can store the values of all the first iterations in an array. Then for the second iteration compare the values from he array, something like this:
it('test', () => {
cy.visit('/landing')
var emailDataVal = []
cy.get('.mailto-obfuscated-email')
.each((emailVal) => {
emailDataVal.push(emailVal.data('value'))
})
.then(() => {
cy.get('.amailto-obfuscated-email').each((emailContent, index) => {
const emailContentText = emailContent.text()
const obfuscateEmailText = emailContentText
.replaceAll('.', '(dotted)')
.replaceAll('#', '(at)')
// ASSERTION
expect(emailDataVal[index]).to.equal(obfuscateEmailText)
})
})
})

It's easier to use .map() than to use .each() for this:
const obfusticate = ($el) => {
return $el.text()
.replaceAll('.', '(dotted)')
.replaceAll('#', '(at)')
}
cy.get('.mailto-obfuscated-email')
.then($els => Cypress.$.map($els, ($el) => $el.data('value')) )
.then(emailDataVals => {
cy.get('.amailto-obfuscated-email')
.then($els => Cypress.$.map($els, ($el) => obfusticate($el)) )
.then(obfusticated => {
expect(emailDataVals).to.deep.equal(obfusticated)
})
})

Related

What is the best way to set a new filteredImages array with useState?

What is the best way to set a new filteredImages array with useState?
I notice I’m doing return attachments.filter(attachment => { … twice, so wondered if I can do it once.
const [filteredImages, setFilteredImages] = useState(() => {
return attachments.filter(attachment => {
const {name, isImage} = attachment;
if (name) {
const newFileFormat = name.split('.').slice(-1)[0];
return isImage && newFileFormat !== 'tiff';
}
});
});
…
useEffect(() => {
setFilteredImages(() => {
return attachments.filter(attachment => {
const {name, isImage} = attachment;
if (name) {
const newFileFormat = name.split('.').slice(-1)[0];
return isImage && newFileFormat !== 'tiff';
}
});
});
}, [attachments, card.attachments]);
I passes an argument to setFilteredImages to set a new filteredImages array but it didn’t work.

ReactJS: Use const from another file

In weights.js I have:
const Weights = ({ data, country, listItemUser, gear }) => {
const newarr = [];
data?.map(el => {
el?.gearHiking?.map(els => {
newarr?.push(els)
})
})
const newarr2 = [];
data?.map(el => {
el?.foodHiking?.map(els => {
newarr2?.push(els)
})
})
const getcamper4x4wei = useMemo(() => {
let initialValue = 0
if (country?.label == "4x4 TOWING CAMPER") {
const gettata = data.filter(el => el.packingLocation == "4x4" ? true : false)
return gettata?.reduce(
(previousValue, currentValue) => previousValue + Number(currentValue.Weight) * Number(currentValue.Quantity)
, initialValue
)
}
}, [data]);
}
export default Weights
and then I import this file in app.js as:
import Weights from './weights'
In app.js how do I access the const of getcamper4x4wei?
Add a return statement to your Weight function:
return getcamper4x4wei;
Then, in app.js, you can access its value - but be aware that Weight now returns a state variable that can change at runtime, so you should use it in useEffect:
// in app.js
useEffect(()=>console.log("Weight changed: ", Weight), [Weight]);

Cannot setstate in nested axios post request in react

I am trying to access the res.data.id from a nested axios.post call and assign it to 'activeId' variable. I am calling the handleSaveAll() function on a button Click event. When the button is clicked, When I console the 'res.data.Id', its returning the value properly, but when I console the 'activeId', it's returning null, which means the 'res.data.id' cannot be assigned. Does anyone have a solution? Thanks in advance
const [activeId, setActiveId] = useState(null);
useEffect(() => {}, [activeId]);
const save1 = () => {
axios.get(api1, getDefaultHeaders())
.then(() => {
const data = {item1: item1,};
axios.post(api2, data, getDefaultHeaders()).then((res) => {
setActiveId(res.data.id);
console.log(res.data.id); // result: e.g. 10
});
});
};
const save2 = () => {
console.log(activeId); // result: null
};
const handleSaveAll = () => {
save1();
save2();
console.log(activeId); // result: again its still null
};
return (
<button type='submit' onClick={handleSaveAll}>Save</button>
);
Setting the state in React acts like an async function.
Meaning that the when you set the state and put a console.log right after it, like in your example, the console.log function runs before the state has actually finished updating.
Which is why we have useEffect, a built-in React hook that activates a callback when one of it's dependencies have changed.
Example:
useEffect(() => {
console.log(activeId);
}, [activeId);
The callback will run every time the state value changes and only after it has finished changing and a render has occurred.
Edit:
Based on the discussion in the comments.
const handleSaveSections = () => {
// ... Your logic with the `setState` at the end.
}
useEffect(() => {
if (activeId === null) {
return;
}
save2(); // ( or any other function / logic you need )
}, [activeId]);
return (
<button onClick={handleSaveSections}>Click me!</button>
)
As the setState is a async task, you will not see the changes directly.
If you want to see the changes after the axios call, you can use the following code :
axios.post(api2, data, getDefaultHeaders())
.then((res) => {
setActiveId(res.data.id)
console.log(res.data.id) // result: e.g. 10
setTimeout(()=>console.log(activeId),0);
})
useEffect(() => {
}, [activeId]);
const [activeId, setActiveId] = useState(null);
const save1 = () => {
const handleSaveSections = async () => {
activeMetric &&
axios.get(api1, getDefaultHeaders()).then(res => {
if (res.data.length > 0) {
Swal.fire({
text: 'Record already exists',
icon: 'error',
});
return false;
}
else {
const data = {
item1: item1,
item2: item2
}
axios.post(api2, data, getDefaultHeaders())
.then((res) => {
setActiveId(res.data.id)
console.log(res.data.id) // result: e.g. 10
})
}
});
}
handleSaveSections()
}
const save2 = () => {
console.log(activeId); //correct result would be shown here
}
const handleSaveAll = () => {
save1();
save2();
}
return (
<button type="submit" onClick={handleSaveAll}>Save</button>
)

Why is this testing in React not working?

I wanted to test that a count increases whenever I clicked on a button, but it seems not to work. Please Help! Here is the code...
describe('checkbtn', () => {
it('onClick', () => {
const { queryByTitle } = render(<Counter />);
const { queryByTitle } = render(<Counter />);
const btn = queryByTitle('button1');
const count = queryByTitle('count');
expect(count.innerHTML).toBe(count.innerHTML);
fireEvent.click(btn);
expect(count.innerHTML).toBe(count.innerHTML + 1);
})
})
First of all you expect some state to equal the same state + 1 here:
expect(count.innerHTML).toBe(count.innerHTML + 1);
It's the same as to write
const x = 2;
expect(x).toBe(x+2)
Second is that you try to add number to string which will result in not what you expect.
What you should do is to write explicit values in your test:
describe('checkbtn', () => {
it('onClick', () => {
const { queryByTitle } = render(<Counter />);
const btn = queryByTitle('button1');
const count = queryByTitle('count');
expect(count.innerHTML).toBe('1');
fireEvent.click(btn);
expect(count.innerHTML).toBe('2');
})
})

Can't display elements of array React

I can see my array in state, but I don't know why elements of array doesn't display on the app interface.
const [members, setMembers] = useState([])
useEffect( () => {
getMembers();
}, [props.event])
const getMembers = () => {
let new_members = [];
console.log(props.event)
props.event && props.event.uczestnicy.map(member => {
member.get().then(doc => {
let new_member;
new_member = {
...doc.data(),
id: doc.id
}
new_members.push(new_member)
})
setMembers(new_members)
})
console.log(new_members)
console.log(members)
}
[...]
{members && members.map(member => {
console.log('mem',member)
return(
<div key={member.id}>
{member.nick}
</div>
)
})}
So I can see this array in Components using React Developer Tools, but even console.log doesn't see it in the moment of performing.
And console.log(new_members) and console.log(members) result :
Your member values are fetch asynchronously, so its ideal if you set state only after all the values are resolved. For this you can use a Promise.all
const getMembers = async () => {
let new_members = [];
console.log(props.event)
if(props.event) {
const val = await Promise.all(props.event.uczestnicy.map(member => {
return member.get().then(doc => {
let new_member;
new_member = {
...doc.data(),
id: doc.id
}
return new_member
})
});
setMembers(values);
console.log(values);
}
}

Resources