diff --git a/client/src/components/About/index.jsx b/client/src/components/About/index.jsx
index effe95f..5243551 100644
--- a/client/src/components/About/index.jsx
+++ b/client/src/components/About/index.jsx
@@ -1,5 +1,5 @@
/* eslint-disable */
-import Reactfrom 'react';
+import React from 'react';
import PropTypes from 'prop-types';
import { COMMIT_SHA } from '@/config/env';
diff --git a/client/src/components/Chat/Chat.jsx b/client/src/components/Chat/Chat.jsx
index a986b90..ad7f15d 100644
--- a/client/src/components/Chat/Chat.jsx
+++ b/client/src/components/Chat/Chat.jsx
@@ -140,7 +140,8 @@ export const Chat = ({ sendEncryptedMessage, showNotice, userId, username, clear
return null;
};
- const handleSendClick = () => {
+ const handleSendClick = evt => {
+ evt.preventDefault();
sendMessage();
textInputRef.current.focus();
};
diff --git a/client/src/components/Chat/Chat.test.jsx b/client/src/components/Chat/Chat.test.jsx
index f38527d..70cfbff 100644
--- a/client/src/components/Chat/Chat.test.jsx
+++ b/client/src/components/Chat/Chat.test.jsx
@@ -207,7 +207,7 @@ describe('Chat component', () => {
fireEvent.keyDown(textarea, { key: 'Enter' });
});
- it('should work with touch support', () => {
+ it('should work with touch support', async () => {
// Enable touch support
dom.hasTouchSupport = true;
@@ -239,15 +239,15 @@ describe('Chat component', () => {
fireEvent.change(textarea, { target: { value: 'test' } });
// Touch send button
- fireEvent.click(getByTitle('Send'));
+ await fireEvent.click(getByTitle('Send'));
expect(sendEncryptedMessage).toHaveBeenLastCalledWith({
payload: { text: 'test', timestamp: 1584183718135 },
type: 'TEXT_MESSAGE',
});
- // Should not send message
- fireEvent.click(getByTitle('Send'));
+ // Should not send message because of the empty message
+ await fireEvent.click(getByTitle('Send'));
expect(sendEncryptedMessage).toHaveBeenCalledTimes(1);
});
diff --git a/client/src/components/Home/ActivityList.test.jsx b/client/src/components/Home/ActivityList.test.jsx
index e6f84d3..c28bc2b 100644
--- a/client/src/components/Home/ActivityList.test.jsx
+++ b/client/src/components/Home/ActivityList.test.jsx
@@ -1,7 +1,7 @@
-import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import { Provider } from 'react-redux';
import { describe, it, expect, vi } from 'vitest';
+import { act } from 'react-dom/test-utils';
import configureStore from '@/store';
@@ -58,21 +58,25 @@ describe('ActivityList component', () => {
,
);
- fireEvent.click(getByText('By using Darkwire, you are agreeing to our Acceptable Use Policy and Terms of Service'));
- vi.runAllTimers();
+ await fireEvent.click(
+ getByText('By using Darkwire, you are agreeing to our Acceptable Use Policy and Terms of Service'),
+ );
+ await act(() => vi.runAllTimers());
expect(mockOpenModal.mock.calls[0][0]).toBe('About');
- vi.runAllTimers();
+ await act(() => vi.runAllTimers());
});
- it('should focus chat', () => {
+ it('should focus chat', async () => {
const { getByTestId } = render(
,
);
- fireEvent.click(getByTestId('main-div'));
- vi.runAllTimers();
+
+ await fireEvent.click(getByTestId('main-div'));
+
+ await act(() => vi.runAllTimers());
});
it('should scroll to bottom on new message if not scrolled', () => {
diff --git a/client/src/components/Home/Home.jsx b/client/src/components/Home/Home.jsx
index 36f1083..b3f7970 100644
--- a/client/src/components/Home/Home.jsx
+++ b/client/src/components/Home/Home.jsx
@@ -290,7 +290,7 @@ const Home = ({
);
};
-const User = ({ createUser, username, ...rest }) => {
+export const WithUser = ({ createUser, username, ...rest }) => {
const [loaded, setLoaded] = React.useState(false);
const loading = React.useRef(false);
@@ -305,6 +305,7 @@ const User = ({ createUser, username, ...rest }) => {
const exportedEncryptDecryptPublicKey = await crypto.exportKey(encryptDecryptKeys.publicKey);
if (!mounted) {
+ loading.current = false;
return;
}
@@ -313,15 +314,18 @@ const User = ({ createUser, username, ...rest }) => {
publicKey: exportedEncryptDecryptPublicKey,
privateKey: exportedEncryptDecryptPrivateKey,
});
+
+ loading.current = false;
setLoaded(true);
};
- if (!loaded) {
+ if (!loaded && !loading.current) {
loading.current = true;
createUserLocal();
}
return () => {
+ loading.current = false;
mounted = false;
};
}, [createUser, loaded, username]);
@@ -332,11 +336,11 @@ const User = ({ createUser, username, ...rest }) => {
return ;
};
-User.defaultProps = {
+WithUser.defaultProps = {
modalComponent: null,
};
-User.propTypes = {
+WithUser.propTypes = {
receiveEncryptedMessage: PropTypes.func.isRequired,
receiveUnencryptedMessage: PropTypes.func.isRequired,
createUser: PropTypes.func.isRequired,
@@ -370,4 +374,4 @@ User.propTypes = {
translations: PropTypes.object.isRequired,
};
-export default User;
+export default WithUser;
diff --git a/client/src/components/Home/Home.test.jsx b/client/src/components/Home/Home.test.jsx
index 4bbd275..213b73a 100644
--- a/client/src/components/Home/Home.test.jsx
+++ b/client/src/components/Home/Home.test.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
import { Provider } from 'react-redux';
import { render } from '@testing-library/react';
import { test, expect, vi } from 'vitest';
@@ -20,10 +19,18 @@ vi.mock('@/utils/socket', () => {
return {
on: vi.fn(),
emit: vi.fn(),
+ close: vi.fn(),
+ };
+ }),
+ getSocket: vi.fn().mockImplementation(() => {
+ return {
+ on: vi.fn(),
+ emit: vi.fn(),
+ close: vi.fn(),
};
}),
};
-}); //
+});
vi.mock('../../utils/crypto', () => {
// Need window.crytpo.subtle
@@ -45,14 +52,13 @@ vi.mock('../../utils/crypto', () => {
});
test('Home component is displaying', async () => {
- const { asFragment } = render(
+ const { asFragment, findByText } = render(
{}}
activities={[]}
- match={{ params: { roomId: 'roomTest' } }}
createUser={() => {}}
toggleSocketConnected={() => {}}
receiveEncryptedMessage={() => {}}
@@ -76,9 +82,16 @@ test('Home component is displaying', async () => {
closeModal={() => {}}
publicKey={{}}
username={'linus'}
+ socketId={'roomTest'}
+ persistenceIsEnabled={false}
+ togglePersistenceEnabled={() => {}}
+ setLanguage={() => {}}
+ language={'en'}
/>
,
);
+ await findByText('Disconnected');
+
expect(asFragment()).toMatchSnapshot();
});
diff --git a/client/src/components/Home/index.jsx b/client/src/components/Home/index.jsx
index 9bd7aa8..c78ff94 100644
--- a/client/src/components/Home/index.jsx
+++ b/client/src/components/Home/index.jsx
@@ -65,14 +65,17 @@ const mapDispatchToProps = {
export const ConnectedHome = connect(mapStateToProps, mapDispatchToProps)(Home);
-const HomeWithParams = ({ ...props }) => {
- const socketId = useLoaderData();
+export const ConnectedHomeWithNotification = ({ socketId, ...props }) => {
return (
);
- // return ;
+};
+
+const HomeWithParams = ({ ...props }) => {
+ const socketId = useLoaderData();
+ return ;
};
export default HomeWithParams;
diff --git a/client/src/components/Home/index.test.jsx b/client/src/components/Home/index.test.jsx
index 80edc5c..a548ce3 100644
--- a/client/src/components/Home/index.test.jsx
+++ b/client/src/components/Home/index.test.jsx
@@ -8,11 +8,10 @@ import configureStore from '@/store';
import { toggleWindowFocus, toggleNotificationEnabled, toggleSoundEnabled } from '@/actions/app';
import { receiveEncryptedMessage } from '@/actions/encrypted_messages';
import { notify, beep } from '@/utils/notifications';
-
-import { ConnectedHome } from './';
-
import { act } from 'react-dom/test-utils';
+import { ConnectedHomeWithNotification } from './';
+
const store = configureStore();
vi.useFakeTimers();
@@ -108,7 +107,7 @@ describe('Connected Home component', () => {
it('should display', async () => {
const { asFragment, findByText } = render(
-
+
,
);
@@ -117,10 +116,10 @@ describe('Connected Home component', () => {
expect(asFragment()).toMatchSnapshot();
});
- it('should set notification', async () => {
+ it('should detect notification granted', async () => {
const { findByText } = render(
-
+
,
);
@@ -128,53 +127,62 @@ describe('Connected Home component', () => {
expect(store.getState().app.notificationIsAllowed).toBe(true);
expect(store.getState().app.notificationIsEnabled).toBe(true);
+ });
+ it('should detect notification denied', async () => {
global.Notification = {
permission: 'denied',
};
- const { findByText: findByText2 } = render(
+ const { findByText } = render(
-
+
,
);
- await findByText2('Disconnected');
+ await findByText('Disconnected');
expect(store.getState().app.notificationIsAllowed).toBe(false);
+ });
+ it('should detect notification default', async () => {
global.Notification = {
permission: 'default',
};
- const { findByText: findByText3 } = render(
+ const { findByText } = render(
-
+
,
);
- await findByText3('Disconnected');
+ await findByText('Disconnected');
expect(store.getState().app.notificationIsAllowed).toBe(null);
});
it('should send notifications', async () => {
Modal.prototype.getSnapshotBeforeUpdate = vi.fn().mockReturnValue(null);
- const { rerender } = render(
+
+ const { rerender, findByText } = render(
-
+
,
);
+ await findByText('Disconnected');
+
// Test with window focused
- await receiveEncryptedMessage({
- type: 'TEXT_MESSAGE',
- payload: {},
- })(store.dispatch, store.getState);
+ await act(() =>
+ receiveEncryptedMessage({
+ type: 'TEXT_MESSAGE',
+ payload: {},
+ })(store.dispatch, store.getState),
+ );
rerender(
-
+
,
);
@@ -184,15 +192,17 @@ describe('Connected Home component', () => {
expect(Tinycon.setBubble).not.toHaveBeenCalled();
// Test with window unfocused
- await toggleWindowFocus(false)(store.dispatch);
- await receiveEncryptedMessage({
- type: 'TEXT_MESSAGE',
- payload: {},
- })(store.dispatch, store.getState);
+ await act(() => toggleWindowFocus(false)(store.dispatch));
+ await act(() =>
+ receiveEncryptedMessage({
+ type: 'TEXT_MESSAGE',
+ payload: {},
+ })(store.dispatch, store.getState),
+ );
rerender(
-
+
,
);
expect(store.getState().app.unreadMessageCount).toBe(1);
@@ -201,22 +211,24 @@ describe('Connected Home component', () => {
expect(Tinycon.setBubble).toHaveBeenLastCalledWith(1);
// Test with sound and notification disabled
- await toggleNotificationEnabled(false)(store.dispatch);
- await toggleSoundEnabled(false)(store.dispatch);
- await receiveEncryptedMessage({
- type: 'TEXT_MESSAGE',
- payload: {},
- })(store.dispatch, store.getState);
+ await act(() => toggleNotificationEnabled(false)(store.dispatch));
+ await act(() => toggleSoundEnabled(false)(store.dispatch));
+ await act(() =>
+ receiveEncryptedMessage({
+ type: 'TEXT_MESSAGE',
+ payload: {},
+ })(store.dispatch, store.getState),
+ );
rerender(
-
+
,
);
expect(store.getState().app.unreadMessageCount).toBe(2);
- expect(notify).toHaveBeenCalledTimes(1);
- expect(beep.play).toHaveBeenCalledTimes(1);
+ expect(notify).toHaveBeenCalledTimes(2);
+ expect(beep.play).toHaveBeenCalledTimes(2);
expect(Tinycon.setBubble).toHaveBeenLastCalledWith(2);
});
});
diff --git a/client/src/reducers/room.js b/client/src/reducers/room.js
index 2cbe8e1..7901d9e 100644
--- a/client/src/reducers/room.js
+++ b/client/src/reducers/room.js
@@ -50,7 +50,7 @@ const room = (state = initialState, action) => {
return {
...state,
members: [
- ...state.members,
+ ...state.members.filter(({ id })=> id !== action.payload.publicKey.n),
{
username: action.payload.username,
publicKey: action.payload.publicKey,