Tip Calculator React

Solution retrospective
I'm proud of how I've organised the state for the tip calculator. This is a code snippet to show what I'm talking about:
export type TipPercentage = {
/** The currently selected preset value */
presetValue: number | null;
/** The currently entered custom value */
customValue: number | null;
/** The currently active mode */
mode: "preset" | "custom";
};
type State = {
billAmount: number | null;
tipPercentage: TipPercentage | null;
numberOfPeople: number | null;
};
type Actions = {
setBillAmount: (amount: number | null) => void;
setNumberOfPeople: (count: number | null) => void;
setPresetTipPercentage: (percentage: number | null) => void;
setCustomTipPercentage: (percentage: number | null) => void;
reset: () => void;
};
const initialState: State = {
billAmount: null,
tipPercentage: null,
numberOfPeople: null,
};
This covers everything that is required of the tip calculator, and (due to the null) is able to handle situations where the various inputs are empty.
I think it would work just as well if I had just used React context and useState
with the state organised in the same manner instead of Zustand. However, I don't think that I would have come up with this without using a state management library.
While writing the UI tests, I came across an issue where the tests ran fine in isolation, but running the whole test suite would have all but the first test run fail.
After a bit of debugging, I found out that there were two (separate) issues causing this.
The first one was that the <App/>
component was being rendered once for each test (without previous instances being removed), therefore the matchers were finding more than one instances of an element from the second test in the suite onwards. I solved this by adding beforeEach
and afterEach
functions to the test suite where the former rendered a new instance of the component and the latter cleaned up the DOM used during testing (using the cleanup
function from the React Testing Library (RTL).
The other was that the values of inputs were being carried over from test to test in the UI test suite. I thought that this would be something concerning the userEvent
from RTL, but apparently it was the Zustand state store. I solved this by resetting the state in the afterEach
function. Maybe I should have mocked the store, but the state reset was simple, and it works well in this case. I did not see any need to complicate the code while the tests (in my opinion) were already close to how the application was supposed to be used.
If anyone has any input on the second issue and how I could handle it better, I would like to hear them out.
Please log in to post a comment
Log in with GitHubCommunity feedback
No feedback yet. Be the first to give feedback on Mirror83's solution.
Join our Discord community
Join thousands of Frontend Mentor community members taking the challenges, sharing resources, helping each other, and chatting about all things front-end!
Join our Discord