Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[feature]: Toasts #1218

Merged
merged 77 commits into from
Jun 3, 2019
Merged
Show file tree
Hide file tree
Changes from 70 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
142c061
WIP: Toasts
sirugh May 7, 2019
71500b0
Updates
sirugh May 8, 2019
69d4097
style feedback per soumya
sirugh May 8, 2019
0f33067
dont need portal right now
sirugh May 8, 2019
2c88043
Remove comment
sirugh May 8, 2019
38677d6
Replace notifications implementation with toasts
sirugh May 8, 2019
6331ab8
Cleanup logo
sirugh May 8, 2019
015fecd
Use toasts for online-offline indicator
sirugh May 8, 2019
9d863ab
cleanup
sirugh May 8, 2019
3359c4b
Add timeout option to toast action
sirugh May 10, 2019
c76a11d
update yarn.lock
sirugh May 10, 2019
96ce559
Add logic to extend timer for duplicate toasts. Add css to pulse border
sirugh May 10, 2019
9d1926f
Merge branch 'develop' into feature/toasts
sirugh May 10, 2019
89b472f
Update toast css to use opactiy animation instead of border
sirugh May 10, 2019
37c83bf
Move online notification to header and fix tests
sirugh May 10, 2019
44713e3
Merge remote-tracking branch 'origin/develop' into feature/toasts
sirugh May 13, 2019
12d198e
Remove yarn lock change
sirugh May 13, 2019
3255b57
Use random key to rerender duplicate toasts for css animation reset
sirugh May 13, 2019
b9de3b2
remove comment
sirugh May 13, 2019
210fdb3
Use a hashing function to make the IDs more readable
sirugh May 13, 2019
fd966ca
Adding logic for duplicate toasts including
sirugh May 13, 2019
51f8e2c
Merge branch 'develop' into feature/toasts
sirugh May 14, 2019
1df8338
Update yarn.lock
sirugh May 14, 2019
847a415
CSS tweaks
sirugh May 14, 2019
5c2cc6f
Proper naming and definition of callback and handler fns
sirugh May 14, 2019
d693c20
Update exports for peregrine
sirugh May 14, 2019
b264249
Add proptypes to header
sirugh May 14, 2019
cbee52c
Update test for header
sirugh May 14, 2019
1cd3943
Unit tests for useToastActions
sirugh May 15, 2019
5f6dfd6
Refactor and unit test useToastContext
sirugh May 15, 2019
89d7d03
Fix test for app
sirugh May 15, 2019
4794929
Merge branch 'develop' into feature/toasts
sirugh May 15, 2019
cc9d4a9
Merge remote-tracking branch 'origin/develop' into feature/toasts
sirugh May 16, 2019
b5f8bcb
prettier
sirugh May 16, 2019
bfb8e23
Only export relevant state instead of context hook
sirugh May 16, 2019
e92a57b
update comment
sirugh May 16, 2019
68d4535
Unit tests for getToastId
sirugh May 17, 2019
c709fe6
Use nextState instead of newState. Destructure previous toast from pr…
sirugh May 17, 2019
d852a88
Dismissable not required, defaults false
sirugh May 17, 2019
dd2326e
Refactor App to be a functional component
sirugh May 17, 2019
2732b3a
Move error notification logic to app
sirugh May 17, 2019
b08635f
Refactor useToastActions to match other hook patterns of returning st…
sirugh May 17, 2019
16a4112
Fix infinite loop in App
jimbo May 18, 2019
1875cc8
Use Map instead of plain object
sirugh May 20, 2019
f74a787
Update actions and container to use map from state
sirugh May 20, 2019
380f7e6
Add toasts to dependency array for callback
sirugh May 20, 2019
3203959
Move state references from action callbacks to reducer.
sirugh May 20, 2019
d025d23
Clean up remove
sirugh May 20, 2019
095476f
Rename test file
sirugh May 20, 2019
46abf3a
Fix app tests
sirugh May 20, 2019
5a2830b
Migrate error notification tests to app
sirugh May 21, 2019
6351fa5
Move online-offline toast emission to app root.
sirugh May 21, 2019
5e2569e
Update packages/peregrine/src/Toasts/useToastContext.js
sirugh May 22, 2019
acfaae7
Addressing feedback
sirugh May 22, 2019
09e44fe
Add stories and fix some css for text wrapping in toasts
sirugh May 22, 2019
2bf4168
Allow async onDismiss or onAction
sirugh May 22, 2019
3c0c582
Move handleAction and handleDismiss creation to the action
sirugh May 22, 2019
0205b87
Display toasts on the right on desktops
sirugh May 22, 2019
674191b
Merge branch 'develop' into feature/toasts
May 24, 2019
b87579d
Update toast id function to only use visual props
sirugh May 24, 2019
49de853
Merge branch 'develop' into feature/toasts
dpatil-magento May 27, 2019
282f65a
Update online icon to match mocks
sirugh May 28, 2019
cbe5894
Fix message content of online toast
sirugh May 28, 2019
0865bc3
add timeout to offline toast
sirugh May 28, 2019
70ccec1
On timeout also invoke the dismiss handler
sirugh May 28, 2019
0d856dd
Revert online toast text per soumya/ux
sirugh May 28, 2019
7df6a2c
Fix for error toasts added within loop that would re-add when one toa…
sirugh May 28, 2019
bf34bf3
Update tests
sirugh May 28, 2019
193e01d
update snaps
sirugh May 29, 2019
159ee04
Merge branch 'develop' into feature/toasts
sirugh May 29, 2019
2e353ac
Merge branch 'develop' into feature/toasts
sirugh May 30, 2019
6cce165
Add functionality for user dismissable toasts that dont time out auto…
sirugh May 31, 2019
68076ff
Extend error timeout to allow time for users to copy error string
sirugh May 31, 2019
b7bb14e
Merge branch 'develop' into feature/toasts
sirugh May 31, 2019
48b83ba
Modify addToast API to accept elements for Icon instead of functions
sirugh May 31, 2019
15a1026
Merge branch 'develop' into feature/toasts
jimbo Jun 3, 2019
b946d2d
Fix icon prop type
jimbo Jun 3, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
329 changes: 329 additions & 0 deletions packages/peregrine/src/Toasts/__tests__/useToastContext.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
import React from 'react';
import { act } from 'react-test-renderer';

import { ToastContextProvider, useToastContext } from '../useToastContext';
import createTestInstance from '../../util/createTestInstance';

jest.mock('react', () => {
const React = jest.requireActual('react');
const spy = jest.spyOn(React, 'useReducer');

return Object.assign(React, { useReducer: spy });
});

const log = jest.fn();

const Component = () => {
const [state, dispatch] = useToastContext();
log(...[state, dispatch]);

return <i />;
};

test('returns state and dispatch', () => {
createTestInstance(
<ToastContextProvider>
<Component />
</ToastContextProvider>
);

expect(log).toHaveBeenCalledTimes(1);
expect(log).toHaveBeenNthCalledWith(
1,
{
toasts: expect.any(Map)
},
expect.any(Function)
);
});

test('handles multiple unique `add` actions', () => {
createTestInstance(
<ToastContextProvider>
<Component />
</ToastContextProvider>
);

const firstToastPayload = {
id: 1,
timestamp: Date.now(),
removalTimeoutId: 2
};
const secondToastPayload = {
id: 2,
timestamp: Date.now(),
removalTimeoutId: 3
};
const [, dispatch] = log.mock.calls[0];

act(() => {
dispatch({
payload: firstToastPayload,
type: 'add'
});
});

act(() => {
dispatch({
payload: secondToastPayload,
type: 'add'
});
});

expect(log).toHaveBeenCalledTimes(3);
expect(log).toHaveBeenNthCalledWith(
1,
{
toasts: expect.any(Map)
},
expect.any(Function)
);
const toastMap = new Map();
toastMap.set(1, {
...firstToastPayload,
timestamp: expect.any(Number),
isDuplicate: false
});

expect(log).toHaveBeenNthCalledWith(
2,
{
toasts: toastMap
},
expect.any(Function)
);

toastMap.set(2, {
...secondToastPayload,
timestamp: expect.any(Number),
isDuplicate: false
});

expect(log).toHaveBeenNthCalledWith(
3,
{
toasts: toastMap
},
expect.any(Function)
);
});

test('handles duplicate `add` actions', () => {
createTestInstance(
<ToastContextProvider>
<Component />
</ToastContextProvider>
);

const payload = {
id: 1,
timestamp: expect.any(Number),
removalTimeoutId: 2
};

const [, dispatch] = log.mock.calls[0];

act(() => {
dispatch({
payload,
type: 'add'
});
});

act(() => {
dispatch({
payload,
type: 'add'
});
});
const toastMap = new Map();

expect(log).toHaveBeenNthCalledWith(
1,
{
toasts: toastMap
},
expect.any(Function)
);

toastMap.set(1, {
...payload,
timestamp: expect.any(Number),
isDuplicate: false
});

expect(log).toHaveBeenNthCalledWith(
2,
{
toasts: toastMap
},
expect.any(Function)
);

toastMap.set(1, {
...payload,
timestamp: expect.any(Number),
isDuplicate: true
});

expect(log).toHaveBeenNthCalledWith(
3,
{
toasts: toastMap
},
expect.any(Function)
);
});

test('handles `remove` action for non-existant toasts', () => {
createTestInstance(
<ToastContextProvider>
<Component />
</ToastContextProvider>
);

const payload = {
id: 1
};
const [, dispatch] = log.mock.calls[0];

act(() => {
dispatch({
payload,
type: 'remove'
});
});

expect(log).toHaveBeenCalledTimes(2);
expect(log).toHaveBeenNthCalledWith(
2,
{
toasts: new Map()
},
expect.any(Function)
);
});

test('handles `remove` action for existing toasts', () => {
createTestInstance(
<ToastContextProvider>
<Component />
</ToastContextProvider>
);

const payload = {
id: 1,
timestamp: Date.now(),
removalTimeoutId: 2
};
const [, dispatch] = log.mock.calls[0];

act(() => {
dispatch({
payload,
type: 'add'
});
});

const toastMap = new Map();
toastMap.set(1, {
...payload,
isDuplicate: false,
timestamp: expect.any(Number)
});

expect(log).toHaveBeenNthCalledWith(
2,
{
toasts: toastMap
},
expect.any(Function)
);

act(() => {
dispatch({
payload: { id: payload.id },
type: 'remove'
});
});

expect(log).toHaveBeenNthCalledWith(
3,
{
toasts: new Map()
},
expect.any(Function)
);
});

test('sets duplicate to false for remaining toasts on removal', () => {
createTestInstance(
<ToastContextProvider>
<Component />
</ToastContextProvider>
);

const payload = {
id: 1,
timestamp: Date.now(),
removalTimeoutId: 2
};
const [, dispatch] = log.mock.calls[0];

act(() => {
dispatch({
payload,
type: 'add'
});
});

act(() => {
dispatch({
payload,
type: 'add'
});
});

act(() => {
dispatch({
payload: { ...payload, id: 3 },
type: 'add'
});
});
const toastMap = new Map();
toastMap.set(1, {
...payload,
isDuplicate: true,
timestamp: expect.any(Number)
});

expect(log).toHaveBeenNthCalledWith(
3,
{
toasts: toastMap
},
expect.any(Function)
);

act(() => {
dispatch({
payload: { id: payload.id },
type: 'remove'
});
});

toastMap.set(3, {
...payload,
isDuplicate: false,
timestamp: expect.any(Number),
id: 3
});

expect(log).toHaveBeenNthCalledWith(
4,
{
toasts: toastMap
},
expect.any(Function)
);
});
Loading