Skip to content

Commit

Permalink
refactor ConnectionStatus from MessageList
Browse files Browse the repository at this point in the history
  • Loading branch information
mahboubii committed Aug 21, 2020
1 parent 32cd623 commit 82c8927
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 12 deletions.
33 changes: 33 additions & 0 deletions src/components/MessageList/ConnectionStatus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// @ts-check
import React, { useContext, useState, useEffect } from 'react';

import { ChatContext, TranslationContext } from '../../context';
import CustomNotification from './CustomNotification';

/**
* ConnectionStatus - Indicator that there is a connection failure
* @type {React.FC<{}>}
*/
const ConnectionStatus = () => {
const { client } = useContext(ChatContext);
const { t } = useContext(TranslationContext);
const [online, setOnline] = useState(true);

useEffect(() => {
/** @param {import('stream-chat').Event<string>} e */
const connectionChanged = (e) => {
if (e.online !== online) setOnline(/** @type {boolean} */ (e.online));
};

client.on('connection.changed', connectionChanged);
return () => client.off('connection.changed', connectionChanged);
}, [client, online]);

return (
<CustomNotification active={!online} type="error">
{t('Connection failure, reconnecting now...')}
</CustomNotification>
);
};

export default React.memo(ConnectionStatus);
14 changes: 2 additions & 12 deletions src/components/MessageList/MessageList.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Channel } from 'stream-chat';
import Center from './Center';
import MessageNotification from './MessageNotification';
import CustomNotification from './CustomNotification';
import ConnectionStatus from './ConnectionStatus';
import MessageListInner from './MessageListInner';
import { MESSAGE_ACTIONS } from '../Message/utils';
import { smartRender } from '../../utils';
Expand All @@ -30,7 +31,6 @@ class MessageList extends PureComponent {

this.state = {
newMessagesNotification: false,
online: true,
notifications: [],
};

Expand All @@ -39,10 +39,6 @@ class MessageList extends PureComponent {
this.notificationTimeouts = [];
}

connectionChanged = ({ online }) => {
if (this.state.online !== online) this.setState({ online });
};

componentDidMount() {
// start at the bottom
this.scrollToBottom();
Expand All @@ -51,13 +47,9 @@ class MessageList extends PureComponent {
this.setState({
messageListRect,
});

this.props.client.on('connection.changed', this.connectionChanged);
}

componentWillUnmount() {
this.props.client.off('connection.changed', this.connectionChanged);

this.notificationTimeouts.forEach(clearTimeout);
}

Expand Down Expand Up @@ -301,9 +293,7 @@ class MessageList extends PureComponent {
</CustomNotification>
))}

<CustomNotification active={!this.state.online} type="error">
{t('Connection failure, reconnecting now...')}
</CustomNotification>
<ConnectionStatus />

<MessageNotification
showNotification={this.state.newMessagesNotification}
Expand Down
68 changes: 68 additions & 0 deletions src/components/MessageList/__tests__/ConnectionStatus.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import testRenderer from 'react-test-renderer';
import { cleanup, render, waitFor, act } from '@testing-library/react';
import { dispatchConnectionChangedEvent, getTestClient } from 'mock-builders';
import '@testing-library/jest-dom';

import ConnectionStatus from '../ConnectionStatus';
import { Chat } from '../../Chat';

const customNotificationId = 'custom-notification';
describe('<ChatContext /> component', () => {
let chatClient;
beforeEach(() => {
chatClient = getTestClient();
});

afterEach(cleanup);

it('should render nothing by default', () => {
const tree = testRenderer.create(
<Chat client={chatClient}>
<ConnectionStatus />
</Chat>,
);

expect(tree.toJSON()).toMatchInlineSnapshot(`null`);
});

it('should render and hide the status based on online state', async () => {
const { queryByTestId } = render(
<Chat client={chatClient}>
<ConnectionStatus />
</Chat>,
);

// default to online
expect(queryByTestId(customNotificationId)).not.toBeInTheDocument();

// offline
act(() => dispatchConnectionChangedEvent(chatClient, false));
await waitFor(() => {
expect(queryByTestId(customNotificationId)).toBeInTheDocument();
});

// online again
act(() => dispatchConnectionChangedEvent(chatClient, true));
await waitFor(() => {
expect(queryByTestId(customNotificationId)).not.toBeInTheDocument();
});
});

it('should render a proper message when client is offline', async () => {
const { queryByTestId } = render(
<Chat client={chatClient}>
<ConnectionStatus />
</Chat>,
);

// offline
act(() => dispatchConnectionChangedEvent(chatClient, false));
await waitFor(() => {
expect(queryByTestId(customNotificationId)).toBeInTheDocument();
expect(queryByTestId(customNotificationId)).toHaveTextContent(
'Connection failure, reconnecting now...',
);
});
});
});

0 comments on commit 82c8927

Please sign in to comment.