Skip to content

Commit cd15400

Browse files
fix: if autoHide changes from true to false, make sure to clear the timer (calintamas#294)
* fix: if the autoHide changes from true to false, make sure to clear the timer * fix: only set visible once options have been set. * test: add tests for autoHide Co-authored-by: Calin Tamas <[email protected]>
1 parent 7d47f49 commit cd15400

File tree

2 files changed

+109
-10
lines changed

2 files changed

+109
-10
lines changed

src/__tests__/Toast.test.tsx

Lines changed: 99 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,7 @@ describe('test Toast component', () => {
5858
<Modal visible={isVisible}>
5959
<Text>Inside modal</Text>
6060
<Button title='Hide modal' onPress={() => setIsVisible(false)} />
61-
<Toast
62-
onShow={onShowInsideModal}
63-
onHide={onHideInsideModal}
64-
/>
61+
<Toast onShow={onShowInsideModal} onHide={onHideInsideModal} />
6562
</Modal>
6663
</>
6764
);
@@ -148,4 +145,102 @@ describe('test Toast component', () => {
148145
});
149146
expect(onShow).not.toHaveBeenCalled();
150147
});
148+
149+
it('when autoHide: true, the Toast only hides when timer reaches visibilityTime', () => {
150+
jest.useFakeTimers();
151+
const onShow = jest.fn();
152+
const onHide = jest.fn();
153+
const visibilityTime = 1500;
154+
155+
render(
156+
<Toast
157+
onShow={onShow}
158+
onHide={onHide}
159+
autoHide={true}
160+
visibilityTime={visibilityTime}
161+
/>
162+
);
163+
164+
act(() => {
165+
Toast.show({
166+
text1: 'I am auto hiding, by default'
167+
});
168+
});
169+
expect(onShow).toHaveBeenCalled();
170+
171+
// Advance time by 1/4 visibilityTime
172+
// Toast should not hide yet
173+
jest.advanceTimersByTime(visibilityTime / 4);
174+
expect(onHide).not.toHaveBeenCalled();
175+
176+
// Do it again 1/4 visibilityTime
177+
// Toast should still be visible
178+
jest.advanceTimersByTime(visibilityTime / 4);
179+
expect(onHide).not.toHaveBeenCalled();
180+
181+
// Advance time by the remaining 1/2 visibilityTime
182+
act(() => {
183+
jest.advanceTimersByTime(visibilityTime / 2);
184+
});
185+
// Now the Toast should hide
186+
expect(onHide).toHaveBeenCalled();
187+
188+
jest.useRealTimers();
189+
});
190+
191+
it('clears previous autoHide: true timer when a new Toast is presented with autoHide: false', () => {
192+
jest.useFakeTimers();
193+
194+
const onShow = jest.fn();
195+
const onHide = jest.fn();
196+
const visibilityTime = 1500;
197+
198+
render(
199+
<Toast
200+
onShow={onShow}
201+
onHide={onHide}
202+
autoHide={true}
203+
visibilityTime={visibilityTime}
204+
/>
205+
);
206+
207+
act(() => {
208+
Toast.show({
209+
text1: 'I am auto hiding, by default'
210+
});
211+
});
212+
expect(onShow).toHaveBeenCalled();
213+
214+
// Advance by 1/2 visibilityTime
215+
// Toast should not hide
216+
jest.advanceTimersByTime(visibilityTime / 2);
217+
expect(onHide).not.toHaveBeenCalled();
218+
219+
// Now, show another Toast, before the previous one has the chance to hide
220+
act(() => {
221+
Toast.show({
222+
text1: 'I am NOT auto hiding',
223+
autoHide: false
224+
});
225+
});
226+
227+
// Advance time to the end of visibilityTime
228+
act(() => {
229+
jest.advanceTimersByTime(visibilityTime / 2);
230+
});
231+
232+
// The new Toast should NOT hide
233+
// (the previous timer should have been cleared before reaching the end)
234+
expect(onHide).not.toHaveBeenCalled();
235+
236+
// And even go beyond visibilityTime
237+
act(() => {
238+
jest.advanceTimersByTime(1000);
239+
});
240+
241+
// The new Toast should still not hide
242+
expect(onHide).not.toHaveBeenCalled();
243+
244+
jest.useRealTimers();
245+
});
151246
});

src/useToast.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,6 @@ export function useToast({ defaultOptions }: UseToastParams) {
7777
onPress = initialOptions.onPress,
7878
props = initialOptions.props
7979
} = params;
80-
// TODO: validate input
81-
// TODO: use a queue when Toast is already visible
82-
setIsVisible(true);
8380
setData({
8481
text1,
8582
text2
@@ -99,17 +96,24 @@ export function useToast({ defaultOptions }: UseToastParams) {
9996
props
10097
}) as Required<ToastOptions>
10198
);
99+
// TODO: validate input
100+
// TODO: use a queue when Toast is already visible
101+
setIsVisible(true);
102102
onShow();
103103
},
104104
[initialOptions, log]
105105
);
106106

107107
React.useEffect(() => {
108108
const { autoHide } = options;
109-
if (isVisible && autoHide) {
110-
startTimer();
109+
if (isVisible) {
110+
if (autoHide) {
111+
startTimer();
112+
} else {
113+
clearTimer();
114+
}
111115
}
112-
}, [isVisible, options, startTimer]);
116+
}, [isVisible, options, startTimer, clearTimer]);
113117

114118
return {
115119
isVisible,

0 commit comments

Comments
 (0)