mirror of
https://github.com/darkwire/darkwire.io.git
synced 2025-07-19 02:59:57 +00:00
Update all dependencies
This commit is contained in:
parent
d0d36d690c
commit
0057292553
@ -4,7 +4,7 @@
|
|||||||
jobs:
|
jobs:
|
||||||
test-job:
|
test-job:
|
||||||
docker:
|
docker:
|
||||||
- image: "circleci/node:lts"
|
- image: "cimg/node:lts"
|
||||||
|
|
||||||
working_directory: ~/repo
|
working_directory: ~/repo
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ jobs:
|
|||||||
command: yarn test
|
command: yarn test
|
||||||
environment:
|
environment:
|
||||||
TZ: UTC
|
TZ: UTC
|
||||||
REACT_APP_COMMIT_SHA: some_sha
|
VITE_COMMIT_SHA: some_sha
|
||||||
|
|
||||||
- store_artifacts: # For coverage report
|
- store_artifacts: # For coverage report
|
||||||
path: client/coverage
|
path: client/coverage
|
||||||
|
8
build.sh
8
build.sh
@ -10,10 +10,10 @@ fi
|
|||||||
echo "building client..."
|
echo "building client..."
|
||||||
cd client
|
cd client
|
||||||
yarn --production=false
|
yarn --production=false
|
||||||
REACT_APP_COMMIT_SHA=$SOURCE_VERSION \
|
VITE_COMMIT_SHA=$SOURCE_VERSION \
|
||||||
REACT_APP_API_HOST=$api_host \
|
VITE_API_HOST=$api_host \
|
||||||
REACT_APP_API_PROTOCOL=$API_PROTOCOL \
|
VITE_API_PROTOCOL=$API_PROTOCOL \
|
||||||
REACT_APP_API_PORT=$API_PORT \
|
VITE_API_PORT=$API_PORT \
|
||||||
yarn build
|
yarn build
|
||||||
cd ../
|
cd ../
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
# Api settings
|
# Api settings
|
||||||
TZ=UTC
|
TZ=UTC
|
||||||
REACT_APP_API_HOST=localhost
|
VITE_API_HOST=localhost
|
||||||
REACT_APP_API_PROTOCOL=http
|
VITE_API_PROTOCOL=http
|
||||||
REACT_APP_API_PORT=3001
|
VITE_API_PORT=3001
|
||||||
REACT_APP_COMMIT_SHA=some_sha
|
VITE_COMMIT_SHA=some_sha
|
||||||
|
|
||||||
# To display darkwire version
|
# To display darkwire version
|
||||||
REACT_APP_COMMIT_SHA=some_sha
|
VITE_COMMIT_SHA=some_sha
|
||||||
|
|
||||||
# Set max transferable file size in MB
|
# Set max transferable file size in MB
|
||||||
REACT_APP_MAX_FILE_SIZE=4
|
VITE_MAX_FILE_SIZE=4
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": ["plugin:prettier/recommended"],
|
|
||||||
"parser": "babel-eslint",
|
|
||||||
"rules": {
|
|
||||||
"prettier/prettier": "error"
|
|
||||||
}
|
|
||||||
}
|
|
10
client/.eslintrc.cjs
Normal file
10
client/.eslintrc.cjs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
plugins: ['@typescript-eslint'],
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
};
|
32
client/.gitignore
vendored
32
client/.gitignore
vendored
@ -1,9 +1,25 @@
|
|||||||
node_modules
|
# Logs
|
||||||
.DS_Store
|
logs
|
||||||
dist
|
|
||||||
coverage
|
|
||||||
*.log
|
*.log
|
||||||
.env*
|
npm-debug.log*
|
||||||
!.env.example
|
yarn-debug.log*
|
||||||
build/
|
yarn-error.log*
|
||||||
*sublime*
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist/
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
@ -1 +0,0 @@
|
|||||||
module.exports = {};
|
|
17
client/index.html
Normal file
17
client/index.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" class="h-100">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="shortcut icon" href="/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<meta name="robots" content="index,nofollow" />
|
||||||
|
<meta name="googlebot" content="index,nofollow" />
|
||||||
|
<meta name="description" content="darkwire.io is the simplest way to chat with encryption online." />
|
||||||
|
<title>Darkwire.io - instant encrypted web chat</title>
|
||||||
|
</head>
|
||||||
|
<body class="h-100">
|
||||||
|
<div id="root" class="h-100"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -6,3 +6,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
"name": "darkwire-client",
|
"name": "darkwire-client",
|
||||||
"version": "2.0.0-beta.12",
|
"version": "2.0.0-beta.12",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
"type": "module",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
{
|
{
|
||||||
"name": "Daniel Seripap"
|
"name": "Daniel Seripap"
|
||||||
@ -12,44 +13,55 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"autosize": "^4.0.2",
|
"bootstrap": "^4.6.2",
|
||||||
"bootstrap": "^4.3.1",
|
"classnames": "^2.3.2",
|
||||||
"clipboard": "^2.0.4",
|
"clipboard": "^2.0.11",
|
||||||
"feather-icons": "^4.21.0",
|
"jquery": "3",
|
||||||
"jquery": "^3.5.0",
|
"js-cookie": "^3.0.1",
|
||||||
"js-cookie": "^2.2.0",
|
"moment": "^2.29.4",
|
||||||
"lodash": "^4.17.20",
|
"nanoid": "^4.0.0",
|
||||||
"moment": "^2.24.0",
|
"randomcolor": "^0.6.2",
|
||||||
"node-sass": "^4.13.1",
|
"react": "^18.2.0",
|
||||||
"popper.js": "^1.15.0",
|
"react-dom": "^18.2.0",
|
||||||
"randomcolor": "^0.5.4",
|
"react-feather": "^2.0.10",
|
||||||
"react": "^16.8.6",
|
"react-linkify": "^1.0.0-alpha",
|
||||||
"react-dom": "^16.8.6",
|
"react-modal": "^3.16.1",
|
||||||
"react-feather": "^1.1.6",
|
"react-redux": "^8.0.5",
|
||||||
"react-linkify": "^0.2.2",
|
"react-router": "^6.4.4",
|
||||||
"react-modal": "^3.8.1",
|
"react-router-dom": "^6.4.4",
|
||||||
"react-redux": "^7.0.3",
|
|
||||||
"react-router-dom": "^5.0.0",
|
|
||||||
"react-scripts": "3.0.0",
|
|
||||||
"react-simple-dropdown": "^3.2.3",
|
"react-simple-dropdown": "^3.2.3",
|
||||||
"redux": "^4.0.1",
|
"redux": "^4.2.0",
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.4.2",
|
||||||
"sanitize-html": "^1.20.1",
|
"sanitize-html": "^2.7.3",
|
||||||
"shortid": "^2.2.14",
|
"socket.io-client": "^4.5.4",
|
||||||
"socket.io-client": "^2.2.0",
|
"tinycon": "^0.6.8"
|
||||||
"tinycon": "^0.6.8",
|
|
||||||
"webcrypto-shim": "^0.1.4"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"dev": "vite",
|
||||||
"build": "react-scripts build",
|
"build": "tsc && vite build",
|
||||||
"test": "react-scripts test --env=jest-environment-jsdom-sixteen",
|
"preview": "vite preview",
|
||||||
"coverage": "react-scripts test --env=jest-environment-jsdom-sixteen --coverage --watchAll=false",
|
"test": "TZ=UTC vitest",
|
||||||
"eject": "react-scripts eject",
|
"lint": "eslint src",
|
||||||
"lint": "eslint src"
|
"coverage": "TZ=UTC vitest --coverage --watch=false"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"devDependencies": {
|
||||||
"extends": "react-app"
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
|
"@testing-library/react": "^13.4.0",
|
||||||
|
"@testing-library/user-event": "^14.4.3",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.46.0",
|
||||||
|
"@typescript-eslint/parser": "^5.46.0",
|
||||||
|
"@vitejs/plugin-react": "^3.0.0",
|
||||||
|
"@vitest/coverage-istanbul": "^0.25.7",
|
||||||
|
"eslint": "^8.29.0",
|
||||||
|
"eslint-config-prettier": "^6.11.0",
|
||||||
|
"eslint-plugin-prettier": "^3.1.3",
|
||||||
|
"jest-environment-jsdom-sixteen": "^1.0.3",
|
||||||
|
"jest-fetch-mock": "^3.0.3",
|
||||||
|
"prettier": "^2.0.5",
|
||||||
|
"sass": "^1.56.2",
|
||||||
|
"typescript": "^4.9.4",
|
||||||
|
"vitest": "^0.25.7",
|
||||||
|
"vitest-fetch-mock": "^0.2.1"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
@ -62,18 +74,5 @@
|
|||||||
"last 1 firefox version",
|
"last 1 firefox version",
|
||||||
"last 1 safari version"
|
"last 1 safari version"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@peculiar/webcrypto": "^1.1.1",
|
|
||||||
"@testing-library/jest-dom": "^5.5.0",
|
|
||||||
"@testing-library/react": "^10.0.4",
|
|
||||||
"enzyme": "^3.9.0",
|
|
||||||
"enzyme-adapter-react-16": "^1.12.1",
|
|
||||||
"enzyme-to-json": "^3.3.5",
|
|
||||||
"eslint-config-prettier": "^6.11.0",
|
|
||||||
"eslint-plugin-prettier": "^3.1.3",
|
|
||||||
"jest-environment-jsdom-sixteen": "^1.0.3",
|
|
||||||
"jest-fetch-mock": "^3.0.3",
|
|
||||||
"prettier": "^2.0.5"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" class="h-100">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<!--
|
|
||||||
manifest.json provides metadata used when your web app is installed on a
|
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
|
||||||
-->
|
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
||||||
<!--
|
|
||||||
Notice the use of %PUBLIC_URL% in the tags above.
|
|
||||||
It will be replaced with the URL of the `public` folder during the build.
|
|
||||||
Only files inside the `public` folder can be referenced from the HTML.
|
|
||||||
|
|
||||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
|
||||||
work correctly both with client-side routing and a non-root public URL.
|
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<meta name="robots" content="index,nofollow" />
|
|
||||||
<meta name="googlebot" content="index,nofollow" />
|
|
||||||
<meta name="description" content="darkwire.io is the simplest way to chat with encryption online." />
|
|
||||||
<title>darkwire.io - instant encrypted web chat</title>
|
|
||||||
</head>
|
|
||||||
<body class="h-100">
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
||||||
<div id="root" class="h-100"></div>
|
|
||||||
<!--
|
|
||||||
This HTML file is a template.
|
|
||||||
If you open it directly in the browser, you will see an empty page.
|
|
||||||
|
|
||||||
You can add webfonts, meta tags, or analytics to this file.
|
|
||||||
The build step will place the bundled scripts into the <body> tag.
|
|
||||||
|
|
||||||
To begin the development, run `npm start` or `yarn start`.
|
|
||||||
To create a production bundle, use `npm run build` or `yarn build`.
|
|
||||||
-->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,5 +1,7 @@
|
|||||||
import * as actions from './app';
|
import * as actions from './app';
|
||||||
|
|
||||||
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
|
|
||||||
describe('App actions', () => {
|
describe('App actions', () => {
|
||||||
it('should create an action to scroll to bottom', () => {
|
it('should create an action to scroll to bottom', () => {
|
||||||
expect(actions.setScrolledToBottom('test')).toEqual({
|
expect(actions.setScrolledToBottom('test')).toEqual({
|
||||||
@ -22,7 +24,7 @@ describe('App actions', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should create an action to clear activities', () => {
|
it('should create an action to clear activities', () => {
|
||||||
const mockDispatch = jest.fn();
|
const mockDispatch = vi.fn();
|
||||||
|
|
||||||
actions.clearActivities()(mockDispatch);
|
actions.clearActivities()(mockDispatch);
|
||||||
|
|
||||||
@ -31,7 +33,7 @@ describe('App actions', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should create all actions', () => {
|
it('should create all actions', () => {
|
||||||
const mockDispatch = jest.fn();
|
const mockDispatch = vi.fn();
|
||||||
|
|
||||||
const actionsResults = [
|
const actionsResults = [
|
||||||
[actions.toggleWindowFocus('test'), 'TOGGLE_WINDOW_FOCUS'],
|
[actions.toggleWindowFocus('test'), 'TOGGLE_WINDOW_FOCUS'],
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { getSocket } from 'utils/socket';
|
import { getSocket } from '@/utils/socket';
|
||||||
import { prepare as prepareMessage, process as processMessage } from 'utils/message';
|
import { prepare as prepareMessage, process as processMessage } from '@/utils/message';
|
||||||
|
|
||||||
export const sendEncryptedMessage = payload => async (dispatch, getState) => {
|
export const sendEncryptedMessage = payload => async (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
import * as actions from './encrypted_messages';
|
import * as actions from './encrypted_messages';
|
||||||
import { getSocket } from 'utils/socket';
|
import { getSocket } from '@/utils/socket';
|
||||||
import { prepare as prepareMessage, process as processMessage } from 'utils/message';
|
import { prepare as prepareMessage, process as processMessage } from '@/utils/message';
|
||||||
|
|
||||||
jest.mock('utils/message', () => {
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
|
|
||||||
|
vi.mock('@/utils/message', () => {
|
||||||
return {
|
return {
|
||||||
prepare: jest
|
prepare: vi
|
||||||
.fn()
|
.fn()
|
||||||
.mockResolvedValue({ original: { type: 'messageType', payload: 'test' }, toSend: 'encryptedpayload' }),
|
.mockResolvedValue({ original: { type: 'messageType', payload: 'test' }, toSend: 'encryptedpayload' }),
|
||||||
process: jest.fn().mockResolvedValue({ type: 'messageType', payload: 'test' }),
|
process: vi.fn().mockResolvedValue({ type: 'messageType', payload: 'test' }),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const mockEmit = jest.fn();
|
const mockEmit = vi.fn();
|
||||||
|
|
||||||
jest.mock('utils/socket', () => {
|
vi.mock('@/utils/socket', () => {
|
||||||
return {
|
return {
|
||||||
getSocket: jest.fn().mockImplementation(() => ({
|
getSocket: vi.fn().mockImplementation(() => ({
|
||||||
emit: mockEmit,
|
emit: mockEmit,
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
@ -23,9 +25,9 @@ jest.mock('utils/socket', () => {
|
|||||||
|
|
||||||
describe('Encrypted messages actions', () => {
|
describe('Encrypted messages actions', () => {
|
||||||
it('should create an action to send message', async () => {
|
it('should create an action to send message', async () => {
|
||||||
const mockDispatch = jest.fn();
|
const mockDispatch = vi.fn();
|
||||||
|
|
||||||
await actions.sendEncryptedMessage({ payload: 'payload' })(mockDispatch, jest.fn().mockReturnValue({ state: {} }));
|
await actions.sendEncryptedMessage({ payload: 'payload' })(mockDispatch, vi.fn().mockReturnValue({ state: {} }));
|
||||||
|
|
||||||
expect(prepareMessage).toHaveBeenLastCalledWith({ payload: 'payload' }, { state: {} });
|
expect(prepareMessage).toHaveBeenLastCalledWith({ payload: 'payload' }, { state: {} });
|
||||||
expect(mockDispatch).toHaveBeenLastCalledWith({ payload: 'test', type: 'SEND_ENCRYPTED_MESSAGE_messageType' });
|
expect(mockDispatch).toHaveBeenLastCalledWith({ payload: 'test', type: 'SEND_ENCRYPTED_MESSAGE_messageType' });
|
||||||
@ -33,11 +35,11 @@ describe('Encrypted messages actions', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should create an action to receive message', async () => {
|
it('should create an action to receive message', async () => {
|
||||||
const mockDispatch = jest.fn();
|
const mockDispatch = vi.fn();
|
||||||
|
|
||||||
await actions.receiveEncryptedMessage({ payload: 'encrypted' })(
|
await actions.receiveEncryptedMessage({ payload: 'encrypted' })(
|
||||||
mockDispatch,
|
mockDispatch,
|
||||||
jest.fn().mockReturnValue({ state: {} }),
|
vi.fn().mockReturnValue({ state: {} }),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(processMessage).toHaveBeenLastCalledWith({ payload: 'encrypted' }, { state: {} });
|
expect(processMessage).toHaveBeenLastCalledWith({ payload: 'encrypted' }, { state: {} });
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { getSocket } from 'utils/socket';
|
import { getSocket } from '@/utils/socket';
|
||||||
|
|
||||||
const receiveUserEnter = (payload, dispatch) => {
|
const receiveUserEnter = (payload, dispatch) => {
|
||||||
dispatch({ type: 'USER_ENTER', payload });
|
dispatch({ type: 'USER_ENTER', payload });
|
||||||
@ -70,7 +70,7 @@ const sendToggleLockRoom = (dispatch, getState) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sendUnencryptedMessage = (type, payload) => async (dispatch, getState) => {
|
export const sendUnencryptedMessage = type => async (dispatch, getState) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'TOGGLE_LOCK_ROOM':
|
case 'TOGGLE_LOCK_ROOM':
|
||||||
return sendToggleLockRoom(dispatch, getState);
|
return sendToggleLockRoom(dispatch, getState);
|
||||||
|
@ -1,33 +1,34 @@
|
|||||||
import * as actions from './unencrypted_messages';
|
import * as actions from './unencrypted_messages';
|
||||||
import { getSocket } from 'utils/socket';
|
|
||||||
|
|
||||||
const mockEmit = jest.fn((_type, _null, callback) => {
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
|
|
||||||
|
const mockEmit = vi.fn((_type, _null, callback) => {
|
||||||
callback({ isLocked: true });
|
callback({ isLocked: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('utils/socket', () => {
|
vi.mock('@/utils/socket', () => {
|
||||||
return {
|
return {
|
||||||
getSocket: jest.fn().mockImplementation(() => ({
|
getSocket: vi.fn().mockImplementation(() => ({
|
||||||
emit: mockEmit,
|
emit: mockEmit,
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Reveice unencrypted message actions', () => {
|
describe('Receive unencrypted message actions', () => {
|
||||||
it('should create no action', () => {
|
it('should create no action', () => {
|
||||||
const mockDispatch = jest.fn();
|
const mockDispatch = vi.fn();
|
||||||
actions.receiveUnencryptedMessage('FAKE')(mockDispatch, jest.fn().mockReturnValue({}));
|
actions.receiveUnencryptedMessage('FAKE')(mockDispatch, vi.fn().mockReturnValue({}));
|
||||||
expect(mockDispatch).not.toHaveBeenCalled();
|
expect(mockDispatch).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create user enter action', () => {
|
it('should create user enter action', () => {
|
||||||
const mockDispatch = jest.fn();
|
const mockDispatch = vi.fn();
|
||||||
actions.receiveUnencryptedMessage('USER_ENTER', 'test')(mockDispatch, jest.fn().mockReturnValue({ state: {} }));
|
actions.receiveUnencryptedMessage('USER_ENTER', 'test')(mockDispatch, vi.fn().mockReturnValue({ state: {} }));
|
||||||
expect(mockDispatch).toHaveBeenLastCalledWith({ type: 'USER_ENTER', payload: 'test' });
|
expect(mockDispatch).toHaveBeenLastCalledWith({ type: 'USER_ENTER', payload: 'test' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create user exit action', () => {
|
it('should create user exit action', () => {
|
||||||
const mockDispatch = jest.fn();
|
const mockDispatch = vi.fn();
|
||||||
const state = {
|
const state = {
|
||||||
room: {
|
room: {
|
||||||
members: [
|
members: [
|
||||||
@ -37,7 +38,7 @@ describe('Reveice unencrypted message actions', () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const mockGetState = jest.fn().mockReturnValue(state);
|
const mockGetState = vi.fn().mockReturnValue(state);
|
||||||
const payload1 = [
|
const payload1 = [
|
||||||
{ publicKey: { n: 'alankey' } },
|
{ publicKey: { n: 'alankey' } },
|
||||||
{ publicKey: { n: 'dankey' } },
|
{ publicKey: { n: 'dankey' } },
|
||||||
@ -62,7 +63,7 @@ describe('Reveice unencrypted message actions', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should create receive toggle lock room action', () => {
|
it('should create receive toggle lock room action', () => {
|
||||||
const mockDispatch = jest.fn();
|
const mockDispatch = vi.fn();
|
||||||
const state = {
|
const state = {
|
||||||
room: {
|
room: {
|
||||||
members: [
|
members: [
|
||||||
@ -71,7 +72,7 @@ describe('Reveice unencrypted message actions', () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const mockGetState = jest.fn().mockReturnValue(state);
|
const mockGetState = vi.fn().mockReturnValue(state);
|
||||||
const payload = { publicKey: { n: 'alankey' } };
|
const payload = { publicKey: { n: 'alankey' } };
|
||||||
|
|
||||||
actions.receiveUnencryptedMessage('TOGGLE_LOCK_ROOM', payload)(mockDispatch, mockGetState);
|
actions.receiveUnencryptedMessage('TOGGLE_LOCK_ROOM', payload)(mockDispatch, mockGetState);
|
||||||
@ -82,14 +83,14 @@ describe('Reveice unencrypted message actions', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should create receive toggle lock room action', () => {
|
it('should create receive toggle lock room action', () => {
|
||||||
const mockDispatch = jest.fn();
|
const mockDispatch = vi.fn();
|
||||||
const state = {
|
const state = {
|
||||||
user: {
|
user: {
|
||||||
username: 'alan',
|
username: 'alan',
|
||||||
id: 'idalan',
|
id: 'idalan',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const mockGetState = jest.fn().mockReturnValue(state);
|
const mockGetState = vi.fn().mockReturnValue(state);
|
||||||
|
|
||||||
actions.sendUnencryptedMessage('TOGGLE_LOCK_ROOM')(mockDispatch, mockGetState);
|
actions.sendUnencryptedMessage('TOGGLE_LOCK_ROOM')(mockDispatch, mockGetState);
|
||||||
expect(mockDispatch).toHaveBeenLastCalledWith({
|
expect(mockDispatch).toHaveBeenLastCalledWith({
|
||||||
@ -101,20 +102,20 @@ describe('Reveice unencrypted message actions', () => {
|
|||||||
|
|
||||||
describe('Send unencrypted message actions', () => {
|
describe('Send unencrypted message actions', () => {
|
||||||
it('should create no action', () => {
|
it('should create no action', () => {
|
||||||
const mockDispatch = jest.fn();
|
const mockDispatch = vi.fn();
|
||||||
actions.sendUnencryptedMessage('FAKE')(mockDispatch, jest.fn().mockReturnValue({}));
|
actions.sendUnencryptedMessage('FAKE')(mockDispatch, vi.fn().mockReturnValue({}));
|
||||||
expect(mockDispatch).not.toHaveBeenCalled();
|
expect(mockDispatch).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create toggle lock room action', () => {
|
it('should create toggle lock room action', () => {
|
||||||
const mockDispatch = jest.fn();
|
const mockDispatch = vi.fn();
|
||||||
const state = {
|
const state = {
|
||||||
user: {
|
user: {
|
||||||
username: 'alan',
|
username: 'alan',
|
||||||
id: 'idalan',
|
id: 'idalan',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const mockGetState = jest.fn().mockReturnValue(state);
|
const mockGetState = vi.fn().mockReturnValue(state);
|
||||||
|
|
||||||
actions.sendUnencryptedMessage('TOGGLE_LOCK_ROOM')(mockDispatch, mockGetState);
|
actions.sendUnencryptedMessage('TOGGLE_LOCK_ROOM')(mockDispatch, mockGetState);
|
||||||
expect(mockDispatch).toHaveBeenLastCalledWith({
|
expect(mockDispatch).toHaveBeenLastCalledWith({
|
||||||
|
@ -3,21 +3,21 @@ let host;
|
|||||||
let protocol;
|
let protocol;
|
||||||
let port;
|
let port;
|
||||||
|
|
||||||
switch (process.env.NODE_ENV) {
|
switch (import.meta.env.NODE_ENV) {
|
||||||
case 'staging':
|
case 'staging':
|
||||||
host = process.env.REACT_APP_API_HOST;
|
host = import.meta.env.VITE_API_HOST;
|
||||||
protocol = process.env.REACT_APP_API_PROTOCOL || 'https';
|
protocol = import.meta.env.VITE_API_PROTOCOL || 'https';
|
||||||
port = process.env.REACT_APP_API_PORT || 443;
|
port = import.meta.env.VITE_API_PORT || 443;
|
||||||
break;
|
break;
|
||||||
case 'production':
|
case 'production':
|
||||||
host = process.env.REACT_APP_API_HOST;
|
host = import.meta.env.VITE_API_HOST;
|
||||||
protocol = process.env.REACT_APP_API_PROTOCOL || 'https';
|
protocol = import.meta.env.VITE_API_PROTOCOL || 'https';
|
||||||
port = process.env.REACT_APP_API_PORT || 443;
|
port = import.meta.env.VITE_API_PORT || 443;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
host = process.env.REACT_APP_API_HOST || 'localhost';
|
host = import.meta.env.VITE_API_HOST || 'localhost';
|
||||||
protocol = process.env.REACT_APP_API_PROTOCOL || 'http';
|
protocol = import.meta.env.VITE_API_PROTOCOL || 'http';
|
||||||
port = process.env.REACT_APP_API_PORT || 3001;
|
port = import.meta.env.VITE_API_PORT || 3001;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, fireEvent, waitFor } from '@testing-library/react';
|
import { render, fireEvent } from '@testing-library/react';
|
||||||
import About from '.';
|
import About from '.';
|
||||||
import fetchMock from 'jest-fetch-mock';
|
import { describe, it, expect, vi, afterEach } from 'vitest';
|
||||||
|
|
||||||
jest.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
|
|
||||||
// Mock Api generator
|
// Mock Api generator
|
||||||
|
|
||||||
jest.mock('../../api/generator', () => {
|
vi.mock('@/api/generator', () => {
|
||||||
return path => {
|
return {
|
||||||
return `http://fakedomain/${path}`;
|
default: path => {
|
||||||
|
return `http://fakedomain/${path}`;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -43,7 +45,7 @@ describe('About component', () => {
|
|||||||
|
|
||||||
fireEvent.change(getByPlaceholderText('Room ID'), { target: { value: 'newRoomName' } });
|
fireEvent.change(getByPlaceholderText('Room ID'), { target: { value: 'newRoomName' } });
|
||||||
|
|
||||||
jest.runAllTimers();
|
vi.runAllTimers();
|
||||||
|
|
||||||
fireEvent.click(getByText('Submit'));
|
fireEvent.click(getByText('Submit'));
|
||||||
|
|
@ -1,12 +1,12 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`About component should display 1`] = `
|
exports[`About component > should display 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div
|
<div
|
||||||
class="base"
|
class="_base_4f26aa"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="links"
|
class="_links_4f26aa"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<a
|
<a
|
@ -1,7 +1,9 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import apiUrlGenerator from '../../api/generator';
|
|
||||||
|
import { COMMIT_SHA } from '@/config/env';
|
||||||
|
import apiUrlGenerator from '@/api/generator';
|
||||||
import styles from './styles.module.scss';
|
import styles from './styles.module.scss';
|
||||||
|
|
||||||
class About extends Component {
|
class About extends Component {
|
||||||
@ -63,11 +65,8 @@ class About extends Component {
|
|||||||
<h4>Version</h4>
|
<h4>Version</h4>
|
||||||
<p>
|
<p>
|
||||||
Commit SHA:{' '}
|
Commit SHA:{' '}
|
||||||
<a
|
<a target="_blank" href={`https://github.com/darkwire/darkwire.io/commit/${COMMIT_SHA}`}>
|
||||||
target="_blank"
|
{COMMIT_SHA}
|
||||||
href={`https://github.com/darkwire/darkwire.io/commit/${process.env.REACT_APP_COMMIT_SHA}`}
|
|
||||||
>
|
|
||||||
{process.env.REACT_APP_COMMIT_SHA}
|
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
@ -1,12 +1,11 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import sanitizeHtml from 'sanitize-html';
|
import sanitizeHtml from 'sanitize-html';
|
||||||
import FileTransfer from 'components/FileTransfer';
|
|
||||||
import { CornerDownRight } from 'react-feather';
|
import { CornerDownRight } from 'react-feather';
|
||||||
import { getSelectedText, hasTouchSupport } from '../../utils/dom';
|
|
||||||
|
|
||||||
// Disable for now
|
import { getSelectedText, hasTouchSupport } from '@/utils/dom';
|
||||||
// import autosize from 'autosize'
|
|
||||||
|
import FileTransfer from '@/components/FileTransfer';
|
||||||
|
|
||||||
export class Chat extends Component {
|
export class Chat extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -21,14 +20,14 @@ export class Chat extends Component {
|
|||||||
{
|
{
|
||||||
command: 'nick',
|
command: 'nick',
|
||||||
description: 'Changes nickname.',
|
description: 'Changes nickname.',
|
||||||
paramaters: ['{username}'],
|
parameters: ['{username}'],
|
||||||
usage: '/nick {username}',
|
usage: '/nick {username}',
|
||||||
scope: 'global',
|
scope: 'global',
|
||||||
action: params => {
|
action: params => {
|
||||||
// eslint-disable-line
|
// eslint-disable-line
|
||||||
let newUsername = params.join(' ') || ''; // eslint-disable-line
|
let newUsername = params.join(' ') || ''; // eslint-disable-line
|
||||||
|
|
||||||
// Remove things that arent digits or chars
|
// Remove things that aren't digits or chars
|
||||||
newUsername = newUsername.replace(/[^A-Za-z0-9]/g, '-');
|
newUsername = newUsername.replace(/[^A-Za-z0-9]/g, '-');
|
||||||
|
|
||||||
const errors = [];
|
const errors = [];
|
@ -1,19 +1,20 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, screen, fireEvent } from '@testing-library/react';
|
import { render, screen, fireEvent } from '@testing-library/react';
|
||||||
|
import { describe, it, expect, vi, afterEach } from 'vitest';
|
||||||
|
|
||||||
import { Chat } from './Chat';
|
import { Chat } from '@/components/Chat/Chat';
|
||||||
|
|
||||||
import * as dom from 'utils/dom';
|
import * as dom from '@/utils/dom';
|
||||||
|
|
||||||
const translations = {
|
const translations = {
|
||||||
typePlaceholder: 'inputplaceholder',
|
typePlaceholder: 'inputplaceholder',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fake date
|
// Fake date
|
||||||
jest.spyOn(global.Date, 'now').mockImplementation(() => new Date('2020-03-14T11:01:58.135Z').valueOf());
|
vi.spyOn(global.Date, 'now').mockImplementation(() => new Date('2020-03-14T11:01:58.135Z').valueOf());
|
||||||
|
|
||||||
// To change touch support
|
// To change touch support
|
||||||
jest.mock('../../utils/dom');
|
vi.mock('@/utils/dom');
|
||||||
|
|
||||||
describe('Chat component', () => {
|
describe('Chat component', () => {
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -39,7 +40,7 @@ describe('Chat component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('can send message', () => {
|
it('can send message', () => {
|
||||||
const sendEncryptedMessage = jest.fn();
|
const sendEncryptedMessage = vi.fn();
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<Chat
|
<Chat
|
||||||
@ -78,7 +79,7 @@ describe('Chat component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("shouldn't send message with Shift+enter", () => {
|
it("shouldn't send message with Shift+enter", () => {
|
||||||
const sendEncryptedMessage = jest.fn();
|
const sendEncryptedMessage = vi.fn();
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<Chat
|
<Chat
|
||||||
@ -115,9 +116,9 @@ describe('Chat component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should send commands', () => {
|
it('should send commands', () => {
|
||||||
const sendEncryptedMessage = jest.fn();
|
const sendEncryptedMessage = vi.fn();
|
||||||
const showNotice = jest.fn();
|
const showNotice = vi.fn();
|
||||||
const clearActivities = jest.fn();
|
const clearActivities = vi.fn();
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<Chat
|
<Chat
|
||||||
@ -210,14 +211,14 @@ describe('Chat component', () => {
|
|||||||
// Enable touch support
|
// Enable touch support
|
||||||
dom.hasTouchSupport = true;
|
dom.hasTouchSupport = true;
|
||||||
|
|
||||||
jest.mock('../../utils/dom', () => {
|
vi.mock('@/utils/dom', () => {
|
||||||
return {
|
return {
|
||||||
getSelectedText: jest.fn(),
|
getSelectedText: vi.fn(),
|
||||||
hasTouchSupport: true,
|
hasTouchSupport: true,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const sendEncryptedMessage = jest.fn();
|
const sendEncryptedMessage = vi.fn();
|
||||||
|
|
||||||
const { getByTitle } = render(
|
const { getByTitle } = render(
|
||||||
<Chat
|
<Chat
|
@ -1,6 +1,6 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`Chat component should display 1`] = `
|
exports[`Chat component > should display 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<form
|
<form
|
||||||
class="chat-preflight-container"
|
class="chat-preflight-container"
|
||||||
@ -13,7 +13,7 @@ exports[`Chat component should display 1`] = `
|
|||||||
class="input-controls"
|
class="input-controls"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="styles icon file-transfer btn btn-link"
|
class="_styles_374fdd icon file-transfer btn btn-link"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="fileInput"
|
id="fileInput"
|
@ -1,6 +1,6 @@
|
|||||||
import Chat from './Chat';
|
import Chat from './Chat';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { clearActivities, showNotice, sendEncryptedMessage } from '../../actions';
|
import { clearActivities, showNotice, sendEncryptedMessage } from '@/actions';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
username: state.user.username,
|
username: state.user.username,
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import Connecting from '.';
|
import Connecting from '.';
|
||||||
|
import { test, expect } from 'vitest';
|
||||||
|
|
||||||
test('Connecting component is displaying', async () => {
|
test('Connecting component is displaying', async () => {
|
||||||
const { asFragment } = render(<Connecting />);
|
const { asFragment } = render(<Connecting />);
|
@ -1,4 +1,4 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`Connecting component is displaying 1`] = `
|
exports[`Connecting component is displaying 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
@ -1,9 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import uuid from 'uuid';
|
import { nanoid } from 'nanoid';
|
||||||
import { File } from 'react-feather';
|
import { File } from 'react-feather';
|
||||||
import { sanitize } from 'utils';
|
|
||||||
import { styles } from './styles.module.scss';
|
import { MAX_FILE_SIZE } from '@/config/env';
|
||||||
|
import { sanitize } from '@/utils';
|
||||||
|
|
||||||
|
import classes from './styles.module.scss';
|
||||||
|
|
||||||
const VALID_FILE_TYPES = [
|
const VALID_FILE_TYPES = [
|
||||||
'png',
|
'png',
|
||||||
@ -24,8 +27,6 @@ const VALID_FILE_TYPES = [
|
|||||||
'css',
|
'css',
|
||||||
];
|
];
|
||||||
|
|
||||||
const MAX_FILE_SIZE = process.env.REACT_APP_MAX_FILE_SIZE || 4;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode the given file to binary string
|
* Encode the given file to binary string
|
||||||
* @param {File} file
|
* @param {File} file
|
||||||
@ -86,7 +87,7 @@ export const FileTransfer = ({ sendEncryptedMessage }) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileId = uuid.v4();
|
const fileId = nanoid();
|
||||||
const fileData = {
|
const fileData = {
|
||||||
id: fileId,
|
id: fileId,
|
||||||
file,
|
file,
|
||||||
@ -129,7 +130,7 @@ export const FileTransfer = ({ sendEncryptedMessage }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${styles} icon file-transfer btn btn-link`}>
|
<div className={`${classes.styles} icon file-transfer btn btn-link`}>
|
||||||
<input placeholder="Choose a file..." type="file" name="fileUploader" id="fileInput" ref={fileInput} />
|
<input placeholder="Choose a file..." type="file" name="fileUploader" id="fileInput" ref={fileInput} />
|
||||||
<label htmlFor="fileInput">
|
<label htmlFor="fileInput">
|
||||||
<File color="#fff" />
|
<File color="#fff" />
|
@ -1,9 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, screen, fireEvent, createEvent } from '@testing-library/react';
|
import { render, screen, fireEvent, createEvent } from '@testing-library/react';
|
||||||
import FileTransfer from '.';
|
import FileTransfer from '.';
|
||||||
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||||
|
|
||||||
// Fake date
|
// Fake date
|
||||||
jest.spyOn(global.Date, 'now').mockImplementation(() => new Date('2020-03-14T11:01:58.135Z').valueOf());
|
vi.spyOn(global.Date, 'now').mockImplementation(() => new Date('2020-03-14T11:01:58.135Z').valueOf());
|
||||||
|
|
||||||
describe('FileTransfer tests', () => {
|
describe('FileTransfer tests', () => {
|
||||||
const { File } = window;
|
const { File } = window;
|
||||||
@ -68,7 +69,7 @@ describe('FileTransfer tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Try to send unsupported file', async () => {
|
it('Try to send unsupported file', async () => {
|
||||||
window.alert = jest.fn();
|
window.alert = vi.fn();
|
||||||
|
|
||||||
render(<FileTransfer sendEncryptedMessage={() => {}} />);
|
render(<FileTransfer sendEncryptedMessage={() => {}} />);
|
||||||
|
|
||||||
@ -86,7 +87,7 @@ describe('FileTransfer tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Try to send too big file', async () => {
|
it('Try to send too big file', async () => {
|
||||||
window.alert = jest.fn();
|
window.alert = vi.fn();
|
||||||
|
|
||||||
render(<FileTransfer sendEncryptedMessage={() => {}} />);
|
render(<FileTransfer sendEncryptedMessage={() => {}} />);
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`FileTransfer tests FileTransfer component is displaying 1`] = `
|
exports[`FileTransfer tests > FileTransfer component is displaying 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div
|
<div
|
||||||
class="styles icon file-transfer btn btn-link"
|
class="_styles_374fdd icon file-transfer btn btn-link"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="fileInput"
|
id="fileInput"
|
@ -1,12 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Message from 'components/Message';
|
|
||||||
import Username from 'components/Username';
|
|
||||||
import Notice from 'components/Notice';
|
|
||||||
import Zoom from 'utils/ImageZoom';
|
|
||||||
import { getObjectUrl } from 'utils/file';
|
|
||||||
|
|
||||||
import T from 'components/T';
|
import Zoom from '@/utils/ImageZoom';
|
||||||
|
import { getObjectUrl } from '@/utils/file';
|
||||||
|
|
||||||
|
import Message from '@/components/Message';
|
||||||
|
import Username from '@/components/Username';
|
||||||
|
import Notice from '@/components/Notice';
|
||||||
|
import T from '@/components/T';
|
||||||
|
|
||||||
const FileDisplay = ({ activity: { fileType, encodedFile, fileName, username }, scrollToBottom }) => {
|
const FileDisplay = ({ activity: { fileType, encodedFile, fileName, username }, scrollToBottom }) => {
|
||||||
const zoomableImage = React.useRef(null);
|
const zoomableImage = React.useRef(null);
|
@ -1,13 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, fireEvent } from '@testing-library/react';
|
import { render, fireEvent } from '@testing-library/react';
|
||||||
import Activity from './Activity';
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import configureStore from 'store';
|
|
||||||
|
import Activity from './Activity';
|
||||||
|
import configureStore from '@/store';
|
||||||
|
|
||||||
const store = configureStore();
|
const store = configureStore();
|
||||||
|
|
||||||
//jest.mock('components/T'); // Need store
|
|
||||||
|
|
||||||
describe('Activity component', () => {
|
describe('Activity component', () => {
|
||||||
it('should display', () => {
|
it('should display', () => {
|
||||||
const activity = {
|
const activity = {
|
||||||
@ -15,7 +15,7 @@ describe('Activity component', () => {
|
|||||||
};
|
};
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Activity activity={activity} scrollToBottom={jest.fn()} />
|
<Activity activity={activity} scrollToBottom={vi.fn()} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ describe('Activity component', () => {
|
|||||||
};
|
};
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Activity activity={activity} scrollToBottom={jest.fn()} />
|
<Activity activity={activity} scrollToBottom={vi.fn()} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ describe('Activity component', () => {
|
|||||||
};
|
};
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Activity activity={activity} scrollToBottom={jest.fn()} />
|
<Activity activity={activity} scrollToBottom={vi.fn()} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ describe('Activity component', () => {
|
|||||||
};
|
};
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Activity activity={activity} scrollToBottom={jest.fn()} />
|
<Activity activity={activity} scrollToBottom={vi.fn()} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ describe('Activity component', () => {
|
|||||||
};
|
};
|
||||||
const { asFragment, rerender } = render(
|
const { asFragment, rerender } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Activity activity={activity} scrollToBottom={jest.fn()} />
|
<Activity activity={activity} scrollToBottom={vi.fn()} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ describe('Activity component', () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Activity activity={activity} scrollToBottom={jest.fn()} />
|
<Activity activity={activity} scrollToBottom={vi.fn()} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ describe('Activity component', () => {
|
|||||||
};
|
};
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Activity activity={activity} scrollToBottom={jest.fn()} />
|
<Activity activity={activity} scrollToBottom={vi.fn()} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ describe('Activity component', () => {
|
|||||||
};
|
};
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Activity activity={activity} scrollToBottom={jest.fn()} />
|
<Activity activity={activity} scrollToBottom={vi.fn()} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ describe('Activity component', () => {
|
|||||||
};
|
};
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Activity activity={activity} scrollToBottom={jest.fn()} />
|
<Activity activity={activity} scrollToBottom={vi.fn()} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -143,11 +143,11 @@ describe('Activity component', () => {
|
|||||||
encodedFile: 'dGV4dGZpbGU=',
|
encodedFile: 'dGV4dGZpbGU=',
|
||||||
fileType: 'text/plain',
|
fileType: 'text/plain',
|
||||||
};
|
};
|
||||||
global.URL.createObjectURL = jest.fn(data => `url:${data}`);
|
global.URL.createObjectURL = vi.fn(data => `url:${data}`);
|
||||||
|
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Activity activity={activity} scrollToBottom={jest.fn()} />
|
<Activity activity={activity} scrollToBottom={vi.fn()} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -155,9 +155,9 @@ describe('Activity component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should display RECEIVE_FILE with image', () => {
|
it('should display RECEIVE_FILE with image', () => {
|
||||||
global.URL.createObjectURL = jest.fn(data => `url:${data}`);
|
global.URL.createObjectURL = vi.fn(data => `url:${data}`);
|
||||||
|
|
||||||
const mockScrollToBottom = jest.fn();
|
const mockScrollToBottom = vi.fn();
|
||||||
|
|
||||||
const activity = {
|
const activity = {
|
||||||
type: 'RECEIVE_FILE',
|
type: 'RECEIVE_FILE',
|
||||||
@ -181,7 +181,7 @@ describe('Activity component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should display SEND_FILE', () => {
|
it('should display SEND_FILE', () => {
|
||||||
global.URL.createObjectURL = jest.fn(data => `url:${data}`);
|
global.URL.createObjectURL = vi.fn(data => `url:${data}`);
|
||||||
const activity = {
|
const activity = {
|
||||||
type: 'SEND_FILE',
|
type: 'SEND_FILE',
|
||||||
username: 'alice',
|
username: 'alice',
|
||||||
@ -192,7 +192,7 @@ describe('Activity component', () => {
|
|||||||
|
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Activity activity={activity} scrollToBottom={jest.fn()} />
|
<Activity activity={activity} scrollToBottom={vi.fn()} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
@ -1,10 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ChatInput from 'components/Chat';
|
|
||||||
import Activity from './Activity';
|
|
||||||
import T from 'components/T';
|
|
||||||
import { defer } from 'lodash';
|
import { defer } from 'lodash';
|
||||||
|
|
||||||
|
import ChatInput from '@/components/Chat';
|
||||||
|
import T from '@/components/T';
|
||||||
|
|
||||||
|
import Activity from './Activity';
|
||||||
import styles from './styles.module.scss';
|
import styles from './styles.module.scss';
|
||||||
|
|
||||||
const ActivityList = ({ activities, openModal }) => {
|
const ActivityList = ({ activities, openModal }) => {
|
@ -1,18 +1,21 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, fireEvent } from '@testing-library/react';
|
import { render, fireEvent } from '@testing-library/react';
|
||||||
import ActivityList from './ActivityList';
|
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import configureStore from 'store';
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
|
|
||||||
|
import configureStore from '@/store';
|
||||||
|
|
||||||
|
import ActivityList from './ActivityList';
|
||||||
|
|
||||||
const store = configureStore();
|
const store = configureStore();
|
||||||
|
|
||||||
jest.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
|
|
||||||
describe('ActivityList component', () => {
|
describe('ActivityList component', () => {
|
||||||
it('should display', () => {
|
it('should display', () => {
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ActivityList openModal={jest.fn()} activities={[]} />
|
<ActivityList openModal={vi.fn()} activities={[]} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -39,7 +42,7 @@ describe('ActivityList component', () => {
|
|||||||
];
|
];
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ActivityList openModal={jest.fn()} activities={activities} />
|
<ActivityList openModal={vi.fn()} activities={activities} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -47,7 +50,7 @@ describe('ActivityList component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should show About modal', async () => {
|
it('should show About modal', async () => {
|
||||||
const mockOpenModal = jest.fn();
|
const mockOpenModal = vi.fn();
|
||||||
|
|
||||||
const { getByText } = render(
|
const { getByText } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
@ -56,43 +59,40 @@ describe('ActivityList component', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
fireEvent.click(getByText('By using Darkwire, you are agreeing to our Acceptable Use Policy and Terms of Service'));
|
fireEvent.click(getByText('By using Darkwire, you are agreeing to our Acceptable Use Policy and Terms of Service'));
|
||||||
jest.runAllTimers();
|
vi.runAllTimers();
|
||||||
|
|
||||||
expect(mockOpenModal.mock.calls[0][0]).toBe('About');
|
expect(mockOpenModal.mock.calls[0][0]).toBe('About');
|
||||||
jest.runAllTimers();
|
vi.runAllTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should focus chat', () => {
|
it('should focus chat', () => {
|
||||||
const { getByTestId } = render(
|
const { getByTestId } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ActivityList openModal={jest.fn()} activities={[]} />
|
<ActivityList openModal={vi.fn()} activities={[]} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
fireEvent.click(getByTestId('main-div'));
|
fireEvent.click(getByTestId('main-div'));
|
||||||
jest.runAllTimers();
|
vi.runAllTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should scroll to bottom on new message if not scrolled', () => {
|
it('should scroll to bottom on new message if not scrolled', () => {
|
||||||
jest.spyOn(Element.prototype, 'clientHeight', 'get').mockReturnValueOnce(400).mockReturnValueOnce(200);
|
vi.spyOn(Element.prototype, 'clientHeight', 'get').mockReturnValueOnce(400).mockReturnValueOnce(200);
|
||||||
|
|
||||||
Element.prototype.getBoundingClientRect = jest
|
Element.prototype.getBoundingClientRect = vi.fn().mockReturnValueOnce({ top: 0 }).mockReturnValueOnce({ top: 261 });
|
||||||
.fn()
|
|
||||||
.mockReturnValueOnce({ top: 0 })
|
|
||||||
.mockReturnValueOnce({ top: 261 });
|
|
||||||
|
|
||||||
jest.spyOn(Element.prototype, 'scrollHeight', 'get').mockReturnValue(42);
|
vi.spyOn(Element.prototype, 'scrollHeight', 'get').mockReturnValue(42);
|
||||||
const mockScrollTop = jest.spyOn(Element.prototype, 'scrollTop', 'set');
|
const mockScrollTop = vi.spyOn(Element.prototype, 'scrollTop', 'set');
|
||||||
|
|
||||||
const { rerender, getByTestId } = render(
|
const { rerender, getByTestId } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ActivityList openModal={jest.fn()} activities={[]} />
|
<ActivityList openModal={vi.fn()} activities={[]} />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ActivityList
|
<ActivityList
|
||||||
openModal={jest.fn()}
|
openModal={vi.fn()}
|
||||||
activities={[
|
activities={[
|
||||||
{
|
{
|
||||||
type: 'TEXT_MESSAGE',
|
type: 'TEXT_MESSAGE',
|
||||||
@ -105,7 +105,7 @@ describe('ActivityList component', () => {
|
|||||||
</Provider>,
|
</Provider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
jest.runAllTimers();
|
vi.runAllTimers();
|
||||||
|
|
||||||
expect(mockScrollTop).toHaveBeenCalledTimes(2);
|
expect(mockScrollTop).toHaveBeenCalledTimes(2);
|
||||||
expect(mockScrollTop).toHaveBeenLastCalledWith(42);
|
expect(mockScrollTop).toHaveBeenLastCalledWith(42);
|
||||||
@ -115,7 +115,7 @@ describe('ActivityList component', () => {
|
|||||||
rerender(
|
rerender(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ActivityList
|
<ActivityList
|
||||||
openModal={jest.fn()}
|
openModal={vi.fn()}
|
||||||
activities={[
|
activities={[
|
||||||
{
|
{
|
||||||
type: 'TEXT_MESSAGE',
|
type: 'TEXT_MESSAGE',
|
@ -1,17 +1,20 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import Crypto from 'utils/crypto';
|
|
||||||
import { connect as connectSocket } from 'utils/socket';
|
|
||||||
import Nav from 'components/Nav';
|
|
||||||
import shortId from 'shortid';
|
|
||||||
import Connecting from 'components/Connecting';
|
|
||||||
import Modal from 'react-modal';
|
import Modal from 'react-modal';
|
||||||
import About from 'components/About';
|
import PropTypes from 'prop-types';
|
||||||
import Settings from 'components/Settings';
|
import { nanoid } from 'nanoid';
|
||||||
import Welcome from 'components/Welcome';
|
|
||||||
import RoomLocked from 'components/RoomLocked';
|
|
||||||
import { X, AlertCircle } from 'react-feather';
|
import { X, AlertCircle } from 'react-feather';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import Crypto from '@/utils/crypto';
|
||||||
|
import { connect as connectSocket } from '@/utils/socket';
|
||||||
|
|
||||||
|
import Nav from '@/components/Nav';
|
||||||
|
import Connecting from '@/components/Connecting';
|
||||||
|
import About from '@/components/About';
|
||||||
|
import Settings from '@/components/Settings';
|
||||||
|
import Welcome from '@/components/Welcome';
|
||||||
|
import RoomLocked from '@/components/RoomLocked';
|
||||||
|
|
||||||
import ActivityList from './ActivityList';
|
import ActivityList from './ActivityList';
|
||||||
|
|
||||||
import styles from './styles.module.scss';
|
import styles from './styles.module.scss';
|
||||||
@ -22,11 +25,9 @@ Modal.setAppElement('#root');
|
|||||||
|
|
||||||
class Home extends Component {
|
class Home extends Component {
|
||||||
async componentWillMount() {
|
async componentWillMount() {
|
||||||
const roomId = encodeURI(this.props.match.params.roomId);
|
|
||||||
|
|
||||||
const user = await this.createUser();
|
const user = await this.createUser();
|
||||||
|
|
||||||
const socket = connectSocket(roomId);
|
const socket = connectSocket(this.props.socketId);
|
||||||
|
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
|
|
||||||
@ -150,7 +151,7 @@ class Home extends Component {
|
|||||||
|
|
||||||
createUser() {
|
createUser() {
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
const username = shortId.generate();
|
const username = nanoid();
|
||||||
|
|
||||||
const encryptDecryptKeys = await crypto.createEncryptDecryptKeys();
|
const encryptDecryptKeys = await crypto.createEncryptDecryptKeys();
|
||||||
const exportedEncryptDecryptPrivateKey = await crypto.exportKey(encryptDecryptKeys.privateKey);
|
const exportedEncryptDecryptPrivateKey = await crypto.exportKey(encryptDecryptKeys.privateKey);
|
||||||
@ -237,7 +238,7 @@ Home.propTypes = {
|
|||||||
username: PropTypes.string.isRequired,
|
username: PropTypes.string.isRequired,
|
||||||
publicKey: PropTypes.object.isRequired,
|
publicKey: PropTypes.object.isRequired,
|
||||||
members: PropTypes.array.isRequired,
|
members: PropTypes.array.isRequired,
|
||||||
match: PropTypes.object.isRequired,
|
socketId: PropTypes.object.isRequired,
|
||||||
roomId: PropTypes.string.isRequired,
|
roomId: PropTypes.string.isRequired,
|
||||||
roomLocked: PropTypes.bool.isRequired,
|
roomLocked: PropTypes.bool.isRequired,
|
||||||
modalComponent: PropTypes.string,
|
modalComponent: PropTypes.string,
|
@ -1,39 +1,47 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from '@testing-library/react';
|
|
||||||
import Home from './Home';
|
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import configureStore from 'store';
|
import { render } from '@testing-library/react';
|
||||||
|
import { test, expect, vi } from 'vitest';
|
||||||
|
|
||||||
|
import Home from './Home';
|
||||||
|
import configureStore from '@/store';
|
||||||
|
|
||||||
const store = configureStore();
|
const store = configureStore();
|
||||||
|
|
||||||
jest.mock('react-modal'); // Cant load modal without root app element
|
vi.mock('react-modal'); // Cant load modal without root app element
|
||||||
jest.mock('utils/socket', () => {
|
|
||||||
|
vi.mock('@/RoomLink');
|
||||||
|
vi.mock('@/components/Nav');
|
||||||
|
|
||||||
|
vi.mock('@/utils/socket', () => {
|
||||||
// Avoid exception
|
// Avoid exception
|
||||||
return {
|
return {
|
||||||
connect: jest.fn().mockImplementation(() => {
|
connect: vi.fn().mockImplementation(() => {
|
||||||
return {
|
return {
|
||||||
on: jest.fn(),
|
on: vi.fn(),
|
||||||
emit: jest.fn(),
|
emit: vi.fn(),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
}); //
|
}); //
|
||||||
|
|
||||||
jest.mock('utils/crypto', () => {
|
vi.mock('../../utils/crypto', () => {
|
||||||
// Need window.crytpo.subtle
|
// Need window.crytpo.subtle
|
||||||
return jest.fn().mockImplementation(() => {
|
return {
|
||||||
return {
|
default: vi.fn().mockImplementation(() => {
|
||||||
createEncryptDecryptKeys: () => {
|
return {
|
||||||
return {
|
createEncryptDecryptKeys: () => {
|
||||||
privateKey: 'private',
|
return {
|
||||||
publicKey: 'public',
|
privateKey: 'private',
|
||||||
};
|
publicKey: 'public',
|
||||||
},
|
};
|
||||||
exportKey: () => {
|
},
|
||||||
return 'exportedkey';
|
exportKey: () => {
|
||||||
},
|
return 'exportedkey';
|
||||||
};
|
},
|
||||||
});
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Home component is displaying', async () => {
|
test('Home component is displaying', async () => {
|
@ -1,8 +1,9 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { notify, beep } from 'utils/notifications';
|
|
||||||
import Tinycon from 'tinycon';
|
import Tinycon from 'tinycon';
|
||||||
import { toggleNotificationAllowed, toggleNotificationEnabled } from 'actions';
|
|
||||||
|
import { notify, beep } from '@/utils/notifications';
|
||||||
|
import { toggleNotificationAllowed, toggleNotificationEnabled } from '@/actions';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
return {
|
return {
|
@ -1,8 +1,8 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`Activity component should display 1`] = `<DocumentFragment />`;
|
exports[`Activity component > should display 1`] = `<DocumentFragment />`;
|
||||||
|
|
||||||
exports[`Activity component should display CHANGE_USERNAME 1`] = `
|
exports[`Activity component > should display CHANGE_USERNAME 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@ -30,7 +30,7 @@ exports[`Activity component should display CHANGE_USERNAME 1`] = `
|
|||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Activity component should display NOTICE 1`] = `
|
exports[`Activity component > should display NOTICE 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@ -44,7 +44,7 @@ exports[`Activity component should display NOTICE 1`] = `
|
|||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Activity component should display RECEIVE_FILE 1`] = `
|
exports[`Activity component > should display RECEIVE_FILE 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div>
|
<div>
|
||||||
<span>
|
<span>
|
||||||
@ -71,7 +71,7 @@ exports[`Activity component should display RECEIVE_FILE 1`] = `
|
|||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Activity component should display RECEIVE_FILE with image 1`] = `
|
exports[`Activity component > should display RECEIVE_FILE with image 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div>
|
<div>
|
||||||
<span>
|
<span>
|
||||||
@ -103,7 +103,7 @@ exports[`Activity component should display RECEIVE_FILE with image 1`] = `
|
|||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Activity component should display SEND_FILE 1`] = `
|
exports[`Activity component > should display SEND_FILE 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@ -128,7 +128,7 @@ exports[`Activity component should display SEND_FILE 1`] = `
|
|||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Activity component should display TEXT_MESSAGE 1`] = `
|
exports[`Activity component > should display TEXT_MESSAGE 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@ -149,17 +149,13 @@ exports[`Activity component should display TEXT_MESSAGE 1`] = `
|
|||||||
<div
|
<div
|
||||||
class="chat"
|
class="chat"
|
||||||
>
|
>
|
||||||
<span
|
Hi!
|
||||||
class="Linkify"
|
|
||||||
>
|
|
||||||
Hi!
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Activity component should display TOGGLE_LOCK_ROOM 1`] = `
|
exports[`Activity component > should display TOGGLE_LOCK_ROOM 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@ -181,7 +177,7 @@ exports[`Activity component should display TOGGLE_LOCK_ROOM 1`] = `
|
|||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Activity component should display TOGGLE_LOCK_ROOM 2`] = `
|
exports[`Activity component > should display TOGGLE_LOCK_ROOM 2`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@ -203,7 +199,7 @@ exports[`Activity component should display TOGGLE_LOCK_ROOM 2`] = `
|
|||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Activity component should display USER_ACTION 1`] = `
|
exports[`Activity component > should display USER_ACTION 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@ -224,7 +220,7 @@ exports[`Activity component should display USER_ACTION 1`] = `
|
|||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Activity component should display USER_ENTER 1`] = `
|
exports[`Activity component > should display USER_ENTER 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@ -246,7 +242,7 @@ exports[`Activity component should display USER_ENTER 1`] = `
|
|||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Activity component should display USER_EXIT 1`] = `
|
exports[`Activity component > should display USER_EXIT 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
@ -1,6 +1,6 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`ActivityList component should display 1`] = `
|
exports[`ActivityList component > should display 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div
|
<div
|
||||||
class="main-chat"
|
class="main-chat"
|
||||||
@ -14,7 +14,7 @@ exports[`ActivityList component should display 1`] = `
|
|||||||
>
|
>
|
||||||
<li>
|
<li>
|
||||||
<p
|
<p
|
||||||
class="tos"
|
class="_tos_0b54d3"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="btn btn-link"
|
class="btn btn-link"
|
||||||
@ -40,7 +40,7 @@ exports[`ActivityList component should display 1`] = `
|
|||||||
class="input-controls"
|
class="input-controls"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="styles icon file-transfer btn btn-link"
|
class="_styles_374fdd icon file-transfer btn btn-link"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="fileInput"
|
id="fileInput"
|
||||||
@ -78,7 +78,7 @@ exports[`ActivityList component should display 1`] = `
|
|||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`ActivityList component should display with activities 1`] = `
|
exports[`ActivityList component > should display with activities 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div
|
<div
|
||||||
class="main-chat"
|
class="main-chat"
|
||||||
@ -92,7 +92,7 @@ exports[`ActivityList component should display with activities 1`] = `
|
|||||||
>
|
>
|
||||||
<li>
|
<li>
|
||||||
<p
|
<p
|
||||||
class="tos"
|
class="_tos_0b54d3"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="btn btn-link"
|
class="btn btn-link"
|
||||||
@ -123,11 +123,7 @@ exports[`ActivityList component should display with activities 1`] = `
|
|||||||
<div
|
<div
|
||||||
class="chat"
|
class="chat"
|
||||||
>
|
>
|
||||||
<span
|
Hi!
|
||||||
class="Linkify"
|
|
||||||
>
|
|
||||||
Hi!
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@ -196,7 +192,7 @@ exports[`ActivityList component should display with activities 1`] = `
|
|||||||
class="input-controls"
|
class="input-controls"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="styles icon file-transfer btn btn-link"
|
class="_styles_374fdd icon file-transfer btn btn-link"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="fileInput"
|
id="fileInput"
|
@ -1,365 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`Home component is displaying 1`] = `
|
|
||||||
<DocumentFragment>
|
|
||||||
<div
|
|
||||||
class="styles h-100"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="nav-container"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="alert-banner"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="icon"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
fill="none"
|
|
||||||
height="15"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="15"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<circle
|
|
||||||
cx="12"
|
|
||||||
cy="12"
|
|
||||||
r="10"
|
|
||||||
/>
|
|
||||||
<line
|
|
||||||
x1="12"
|
|
||||||
x2="12"
|
|
||||||
y1="8"
|
|
||||||
y2="12"
|
|
||||||
/>
|
|
||||||
<line
|
|
||||||
x1="12"
|
|
||||||
x2="12"
|
|
||||||
y1="16"
|
|
||||||
y2="16"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
Disconnected
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<nav
|
|
||||||
class="navbar navbar-expand-md navbar-dark"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="meta"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="Darkwire"
|
|
||||||
class="logo"
|
|
||||||
src="logo.png"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
class="btn btn-plain btn-link clipboard-trigger room-id ellipsis"
|
|
||||||
data-clipboard-text="http://localhost/testId"
|
|
||||||
data-placement="bottom"
|
|
||||||
data-toggle="tooltip"
|
|
||||||
>
|
|
||||||
/testId
|
|
||||||
</button>
|
|
||||||
<span
|
|
||||||
class="lock-room-container"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="lock-room btn btn-link btn-plain"
|
|
||||||
data-placement="bottom"
|
|
||||||
data-toggle="tooltip"
|
|
||||||
title="You must be the owner to lock or unlock the room"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
class="muted"
|
|
||||||
fill="none"
|
|
||||||
height="24"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<rect
|
|
||||||
height="11"
|
|
||||||
rx="2"
|
|
||||||
ry="2"
|
|
||||||
width="18"
|
|
||||||
x="3"
|
|
||||||
y="11"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M7 11V7a5 5 0 0 1 9.9-1"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
<div
|
|
||||||
class="dropdown members-dropdown"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
class="dropdown__trigger "
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="btn btn-link btn-plain members-action"
|
|
||||||
title="Users"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
class="users-icon"
|
|
||||||
fill="none"
|
|
||||||
height="24"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"
|
|
||||||
/>
|
|
||||||
<circle
|
|
||||||
cx="9"
|
|
||||||
cy="7"
|
|
||||||
r="4"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M23 21v-2a4 4 0 0 0-3-3.87"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M16 3.13a4 4 0 0 1 0 7.75"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<span>
|
|
||||||
0
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<div
|
|
||||||
class="dropdown__content "
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
class="plain"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
aria-controls="navbarSupportedContent"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-label="Toggle navigation"
|
|
||||||
class="navbar-toggler"
|
|
||||||
data-target="#navbarSupportedContent"
|
|
||||||
data-toggle="collapse"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="navbar-toggler-icon"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
<div
|
|
||||||
class="collapse navbar-collapse"
|
|
||||||
id="navbarSupportedContent"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
class="navbar-nav ml-auto"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
class="nav-item"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="btn btn-plain nav-link"
|
|
||||||
target="blank"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
fill="none"
|
|
||||||
height="24"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<circle
|
|
||||||
cx="12"
|
|
||||||
cy="12"
|
|
||||||
r="10"
|
|
||||||
/>
|
|
||||||
<line
|
|
||||||
x1="12"
|
|
||||||
x2="12"
|
|
||||||
y1="8"
|
|
||||||
y2="16"
|
|
||||||
/>
|
|
||||||
<line
|
|
||||||
x1="8"
|
|
||||||
x2="16"
|
|
||||||
y1="12"
|
|
||||||
y2="12"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
<span />
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class=" nav-item"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="btn btn-plain nav-link"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
fill="none"
|
|
||||||
height="24"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<circle
|
|
||||||
cx="12"
|
|
||||||
cy="12"
|
|
||||||
r="3"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
<span />
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class="nav-item"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="btn btn-plain nav-link"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
fill="none"
|
|
||||||
height="24"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<circle
|
|
||||||
cx="12"
|
|
||||||
cy="12"
|
|
||||||
r="10"
|
|
||||||
/>
|
|
||||||
<line
|
|
||||||
x1="12"
|
|
||||||
x2="12"
|
|
||||||
y1="16"
|
|
||||||
y2="12"
|
|
||||||
/>
|
|
||||||
<line
|
|
||||||
x1="12"
|
|
||||||
x2="12"
|
|
||||||
y1="8"
|
|
||||||
y2="8"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
<span />
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="main-chat"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="message-stream h-100"
|
|
||||||
data-testid="main-div"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
class="plain"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<p
|
|
||||||
class="tos"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="btn btn-link"
|
|
||||||
>
|
|
||||||
By using Darkwire, you are agreeing to our Acceptable Use Policy and Terms of Service
|
|
||||||
</button>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="chat-container"
|
|
||||||
>
|
|
||||||
<form
|
|
||||||
class="chat-preflight-container"
|
|
||||||
>
|
|
||||||
<textarea
|
|
||||||
class="chat"
|
|
||||||
placeholder="Type here"
|
|
||||||
rows="1"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="input-controls"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="styles icon file-transfer btn btn-link"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
id="fileInput"
|
|
||||||
name="fileUploader"
|
|
||||||
placeholder="Choose a file..."
|
|
||||||
type="file"
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
for="fileInput"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
fill="none"
|
|
||||||
height="24"
|
|
||||||
stroke="#fff"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"
|
|
||||||
/>
|
|
||||||
<polyline
|
|
||||||
points="13 2 13 9 20 9"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</DocumentFragment>
|
|
||||||
`;
|
|
128
client/src/components/Home/__snapshots__/Home.test.jsx.snap
Normal file
128
client/src/components/Home/__snapshots__/Home.test.jsx.snap
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
|
exports[`Home component is displaying 1`] = `
|
||||||
|
<DocumentFragment>
|
||||||
|
<div
|
||||||
|
class="_styles_0b54d3 h-100"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="nav-container"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="alert-banner"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="icon"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
height="15"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="15"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<circle
|
||||||
|
cx="12"
|
||||||
|
cy="12"
|
||||||
|
r="10"
|
||||||
|
/>
|
||||||
|
<line
|
||||||
|
x1="12"
|
||||||
|
x2="12"
|
||||||
|
y1="8"
|
||||||
|
y2="12"
|
||||||
|
/>
|
||||||
|
<line
|
||||||
|
x1="12"
|
||||||
|
x2="12.01"
|
||||||
|
y1="16"
|
||||||
|
y2="16"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
Disconnected
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="main-chat"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="message-stream h-100"
|
||||||
|
data-testid="main-div"
|
||||||
|
>
|
||||||
|
<ul
|
||||||
|
class="plain"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<p
|
||||||
|
class="_tos_0b54d3"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="btn btn-link"
|
||||||
|
>
|
||||||
|
By using Darkwire, you are agreeing to our Acceptable Use Policy and Terms of Service
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="chat-container"
|
||||||
|
>
|
||||||
|
<form
|
||||||
|
class="chat-preflight-container"
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
class="chat"
|
||||||
|
placeholder="Type here"
|
||||||
|
rows="1"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="input-controls"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="_styles_374fdd icon file-transfer btn btn-link"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
id="fileInput"
|
||||||
|
name="fileUploader"
|
||||||
|
placeholder="Choose a file..."
|
||||||
|
type="file"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
for="fileInput"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
height="24"
|
||||||
|
stroke="#fff"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"
|
||||||
|
/>
|
||||||
|
<polyline
|
||||||
|
points="13 2 13 9 20 9"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DocumentFragment>
|
||||||
|
`;
|
@ -1,9 +1,9 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`Connected Home component should display 1`] = `
|
exports[`Connected Home component > should display 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div
|
<div
|
||||||
class="styles h-100"
|
class="_styles_0b54d3 h-100"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="nav-container"
|
class="nav-container"
|
||||||
@ -38,7 +38,7 @@ exports[`Connected Home component should display 1`] = `
|
|||||||
/>
|
/>
|
||||||
<line
|
<line
|
||||||
x1="12"
|
x1="12"
|
||||||
x2="12"
|
x2="12.01"
|
||||||
y1="16"
|
y1="16"
|
||||||
y2="16"
|
y2="16"
|
||||||
/>
|
/>
|
||||||
@ -58,11 +58,11 @@ exports[`Connected Home component should display 1`] = `
|
|||||||
<img
|
<img
|
||||||
alt="Darkwire"
|
alt="Darkwire"
|
||||||
class="logo"
|
class="logo"
|
||||||
src="logo.png"
|
src="/src/img/logo.png"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
class="btn btn-plain btn-link clipboard-trigger room-id ellipsis"
|
class="btn btn-plain btn-link clipboard-trigger room-id ellipsis"
|
||||||
data-clipboard-text="http://localhost/"
|
data-clipboard-text="http://localhost:3000/"
|
||||||
data-placement="bottom"
|
data-placement="bottom"
|
||||||
data-toggle="tooltip"
|
data-toggle="tooltip"
|
||||||
title="Copied"
|
title="Copied"
|
||||||
@ -218,7 +218,7 @@ exports[`Connected Home component should display 1`] = `
|
|||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
class=" nav-item"
|
class="nav-item"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="btn btn-plain nav-link"
|
class="btn btn-plain nav-link"
|
||||||
@ -279,7 +279,7 @@ exports[`Connected Home component should display 1`] = `
|
|||||||
/>
|
/>
|
||||||
<line
|
<line
|
||||||
x1="12"
|
x1="12"
|
||||||
x2="12"
|
x2="12.01"
|
||||||
y1="8"
|
y1="8"
|
||||||
y2="8"
|
y2="8"
|
||||||
/>
|
/>
|
@ -1,5 +1,6 @@
|
|||||||
import Home from './Home';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { useLoaderData } from 'react-router-dom';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
receiveEncryptedMessage,
|
receiveEncryptedMessage,
|
||||||
createUser,
|
createUser,
|
||||||
@ -14,7 +15,9 @@ import {
|
|||||||
sendUnencryptedMessage,
|
sendUnencryptedMessage,
|
||||||
sendEncryptedMessage,
|
sendEncryptedMessage,
|
||||||
setLanguage,
|
setLanguage,
|
||||||
} from 'actions';
|
} from '@/actions';
|
||||||
|
|
||||||
|
import Home from './Home';
|
||||||
import WithNewMessageNotification from './WithNewMessageNotification';
|
import WithNewMessageNotification from './WithNewMessageNotification';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
@ -57,4 +60,11 @@ const mapDispatchToProps = {
|
|||||||
setLanguage,
|
setLanguage,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WithNewMessageNotification(connect(mapStateToProps, mapDispatchToProps)(Home));
|
export const ConnectedHome = WithNewMessageNotification(connect(mapStateToProps, mapDispatchToProps)(Home));
|
||||||
|
|
||||||
|
const HomeWithParams = ({ ...props }) => {
|
||||||
|
const socketId = useLoaderData();
|
||||||
|
return <ConnectedHome socketId={socketId} {...props} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HomeWithParams;
|
@ -1,88 +1,93 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import ConnectedHome from '.';
|
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import configureStore from 'store';
|
|
||||||
import { toggleWindowFocus, toggleNotificationEnabled, toggleSoundEnabled } from 'actions/app';
|
|
||||||
import { receiveEncryptedMessage } from 'actions/encrypted_messages';
|
|
||||||
import { notify, beep } from 'utils/notifications';
|
|
||||||
import Tinycon from 'tinycon';
|
import Tinycon from 'tinycon';
|
||||||
import Modal from 'react-modal';
|
import Modal from 'react-modal';
|
||||||
|
import { expect, vi, describe, beforeEach, afterEach, it } from 'vitest';
|
||||||
|
|
||||||
|
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 './';
|
||||||
|
|
||||||
const store = configureStore();
|
const store = configureStore();
|
||||||
|
|
||||||
jest.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
|
|
||||||
// We don't test activity list here
|
vi.mock('react-modal'); // Cant load modal without root app element
|
||||||
jest.mock('./ActivityList', () => {
|
|
||||||
return jest.fn().mockReturnValue(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.mock('react-modal'); // Cant load modal without root app element
|
vi.mock('nanoid', () => {
|
||||||
|
|
||||||
jest.mock('utils/socket', () => {
|
|
||||||
// Avoid exception
|
// Avoid exception
|
||||||
return {
|
return {
|
||||||
connect: jest.fn().mockImplementation(() => {
|
nanoid: vi.fn().mockImplementation(() => {
|
||||||
return {
|
|
||||||
on: jest.fn(),
|
|
||||||
emit: jest.fn(),
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
getSocket: jest.fn().mockImplementation(() => {
|
|
||||||
return {
|
|
||||||
on: jest.fn(),
|
|
||||||
emit: jest.fn(),
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.mock('shortid', () => {
|
|
||||||
// Avoid exception
|
|
||||||
return {
|
|
||||||
generate: jest.fn().mockImplementation(() => {
|
|
||||||
return 'shortidgenerated';
|
return 'shortidgenerated';
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('utils/crypto', () => {
|
vi.mock('tinycon', () => {
|
||||||
// Need window.crytpo.subtle
|
return {
|
||||||
return jest.fn().mockImplementation(() => {
|
default: { setBubble: vi.fn() },
|
||||||
return {
|
};
|
||||||
createEncryptDecryptKeys: () => {
|
|
||||||
return {
|
|
||||||
privateKey: { n: 'private' },
|
|
||||||
publicKey: { n: 'public' },
|
|
||||||
};
|
|
||||||
},
|
|
||||||
exportKey: () => {
|
|
||||||
return { n: 'exportedKey' };
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('utils/message', () => {
|
// We don't test activity list here
|
||||||
|
vi.mock('./ActivityList', () => {
|
||||||
|
return { default: vi.fn().mockReturnValue(null) };
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.mock('@/utils/socket', () => {
|
||||||
|
// Avoid exception
|
||||||
return {
|
return {
|
||||||
process: jest.fn(async (payload, state) => ({
|
connect: vi.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
on: vi.fn(),
|
||||||
|
emit: vi.fn(),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
getSocket: vi.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
on: vi.fn(),
|
||||||
|
emit: vi.fn(),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.mock('@/utils/crypto', () => {
|
||||||
|
// Need window.crytpo.subtle
|
||||||
|
return {
|
||||||
|
default: vi.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
createEncryptDecryptKeys: () => {
|
||||||
|
return {
|
||||||
|
privateKey: { n: 'private' },
|
||||||
|
publicKey: { n: 'public' },
|
||||||
|
};
|
||||||
|
},
|
||||||
|
exportKey: () => {
|
||||||
|
return { n: 'exportedKey' };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.mock('@/utils/message', () => {
|
||||||
|
return {
|
||||||
|
process: vi.fn(async (payload, state) => ({
|
||||||
...payload,
|
...payload,
|
||||||
payload: { payload: 'text', username: 'sender', text: 'new message' },
|
payload: { payload: 'text', username: 'sender', text: 'new message' },
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('utils/notifications', () => {
|
vi.mock('@/utils/notifications', () => {
|
||||||
return {
|
return {
|
||||||
notify: jest.fn(),
|
notify: vi.fn(),
|
||||||
beep: { play: jest.fn() },
|
beep: { play: vi.fn() },
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.mock('tinycon', () => {
|
|
||||||
return {
|
|
||||||
setBubble: jest.fn(),
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -143,7 +148,7 @@ describe('Connected Home component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should send notifications', async () => {
|
it('should send notifications', async () => {
|
||||||
Modal.prototype.getSnapshotBeforeUpdate = jest.fn().mockReturnValue(null);
|
Modal.prototype.getSnapshotBeforeUpdate = vi.fn().mockReturnValue(null);
|
||||||
const { rerender } = render(
|
const { rerender } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ConnectedHome match={{ params: { roomId: 'roomTest' } }} userId="testUserId" roomId={'testId'} />
|
<ConnectedHome match={{ params: { roomId: 'roomTest' } }} userId="testUserId" roomId={'testId'} />
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import Message from '.';
|
import Message from '.';
|
||||||
|
import { test, expect } from 'vitest';
|
||||||
|
|
||||||
test('Message component is displaying', async () => {
|
test('Message component is displaying', async () => {
|
||||||
const { asFragment } = render(<Message sender={'linus'} timestamp={1588794269074} message={'we come in peace'} />);
|
const { asFragment } = render(<Message sender={'linus'} timestamp={1588794269074} message={'we come in peace'} />);
|
@ -1,4 +1,4 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`Message component is displaying 1`] = `
|
exports[`Message component is displaying 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
@ -21,11 +21,7 @@ exports[`Message component is displaying 1`] = `
|
|||||||
<div
|
<div
|
||||||
class="chat"
|
class="chat"
|
||||||
>
|
>
|
||||||
<span
|
we come in peace
|
||||||
class="Linkify"
|
|
||||||
>
|
|
||||||
we come in peace
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DocumentFragment>
|
</DocumentFragment>
|
@ -1,9 +1,10 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Username from 'components/Username';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import Linkify from 'react-linkify';
|
import Linkify from 'react-linkify';
|
||||||
|
|
||||||
|
import Username from '@/components/Username';
|
||||||
|
|
||||||
class Message extends Component {
|
class Message extends Component {
|
||||||
render() {
|
render() {
|
||||||
const msg = decodeURI(this.props.message);
|
const msg = decodeURI(this.props.message);
|
@ -1,38 +1,41 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, fireEvent, waitFor } from '@testing-library/react';
|
import { render, fireEvent, waitFor } from '@testing-library/react';
|
||||||
import Nav from '.';
|
|
||||||
import mock$ from 'jquery';
|
import mock$ from 'jquery';
|
||||||
|
import { test, expect, vi } from 'vitest';
|
||||||
|
|
||||||
const mockTooltip = jest.fn().mockImplementation(param => {
|
import Nav from '.';
|
||||||
|
|
||||||
|
const mockTooltip = vi.fn().mockImplementation(param => {
|
||||||
// console.log('tooltip', param);
|
// console.log('tooltip', param);
|
||||||
});
|
});
|
||||||
|
|
||||||
const mockCollapse = jest.fn().mockImplementation(param => {
|
const mockCollapse = vi.fn().mockImplementation(param => {
|
||||||
// console.log('collapse', param);
|
// console.log('collapse', param);
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('jquery', () => {
|
vi.mock('jquery', () => {
|
||||||
return jest.fn().mockImplementation(param => {
|
return {
|
||||||
// console.log('$', param);
|
default: vi.fn().mockImplementation(param => {
|
||||||
if (typeof param === 'function') {
|
if (typeof param === 'function') {
|
||||||
param();
|
param();
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
tooltip: mockTooltip,
|
tooltip: mockTooltip,
|
||||||
collapse: mockCollapse,
|
collapse: mockCollapse,
|
||||||
};
|
};
|
||||||
});
|
}),
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('shortid', () => {
|
vi.mock('nanoid', () => {
|
||||||
return {
|
return {
|
||||||
generate() {
|
nanoid: () => {
|
||||||
return 'fakeid';
|
return 'fakeid';
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
|
|
||||||
const mockTranslations = {
|
const mockTranslations = {
|
||||||
newRoomButton: 'new room',
|
newRoomButton: 'new room',
|
||||||
@ -101,9 +104,9 @@ test('Nav component is displaying with another configuration and can rerender',
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Can copy room url', async () => {
|
test('Can copy room url', async () => {
|
||||||
document.execCommand = jest.fn(() => true);
|
document.execCommand = vi.fn(() => true);
|
||||||
|
|
||||||
const toggleLockRoom = jest.fn();
|
const toggleLockRoom = vi.fn();
|
||||||
|
|
||||||
const { getByText } = render(
|
const { getByText } = render(
|
||||||
<Nav
|
<Nav
|
||||||
@ -128,14 +131,14 @@ test('Can copy room url', async () => {
|
|||||||
expect(mockTooltip).toHaveBeenLastCalledWith('show');
|
expect(mockTooltip).toHaveBeenLastCalledWith('show');
|
||||||
|
|
||||||
// Wait tooltip closing
|
// Wait tooltip closing
|
||||||
jest.runAllTimers();
|
vi.runAllTimers();
|
||||||
|
|
||||||
expect(mock$).toHaveBeenCalledTimes(18);
|
expect(mock$).toHaveBeenCalledTimes(18);
|
||||||
expect(mockTooltip).toHaveBeenLastCalledWith('hide');
|
expect(mockTooltip).toHaveBeenLastCalledWith('hide');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Can lock/unlock room is room owner only', async () => {
|
test('Can lock/unlock room is room owner only', async () => {
|
||||||
const toggleLockRoom = jest.fn();
|
const toggleLockRoom = vi.fn();
|
||||||
|
|
||||||
const { rerender, getByTitle } = render(
|
const { rerender, getByTitle } = render(
|
||||||
<Nav
|
<Nav
|
||||||
@ -231,7 +234,7 @@ test('Can show user list', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Can open settings', async () => {
|
test('Can open settings', async () => {
|
||||||
const openModal = jest.fn();
|
const openModal = vi.fn();
|
||||||
|
|
||||||
// Test with one user owner and me
|
// Test with one user owner and me
|
||||||
const { getByText } = render(
|
const { getByText } = render(
|
||||||
@ -255,7 +258,7 @@ test('Can open settings', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Can open About', async () => {
|
test('Can open About', async () => {
|
||||||
const openModal = jest.fn();
|
const openModal = vi.fn();
|
||||||
|
|
||||||
// Test with one user owner and me
|
// Test with one user owner and me
|
||||||
const { getByText } = render(
|
const { getByText } = render(
|
||||||
@ -279,7 +282,7 @@ test('Can open About', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Can open About', async () => {
|
test('Can open About', async () => {
|
||||||
window.open = jest.fn();
|
window.open = vi.fn();
|
||||||
|
|
||||||
// Test with one user owner and me
|
// Test with one user owner and me
|
||||||
const { getByText } = render(
|
const { getByText } = render(
|
@ -1,4 +1,4 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`Nav component is displaying 1`] = `
|
exports[`Nav component is displaying 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
@ -11,11 +11,11 @@ exports[`Nav component is displaying 1`] = `
|
|||||||
<img
|
<img
|
||||||
alt="Darkwire"
|
alt="Darkwire"
|
||||||
class="logo"
|
class="logo"
|
||||||
src="logo.png"
|
src="/src/img/logo.png"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
class="btn btn-plain btn-link clipboard-trigger room-id ellipsis"
|
class="btn btn-plain btn-link clipboard-trigger room-id ellipsis"
|
||||||
data-clipboard-text="http://localhost/testRoom"
|
data-clipboard-text="http://localhost:3000/testRoom"
|
||||||
data-placement="bottom"
|
data-placement="bottom"
|
||||||
data-toggle="tooltip"
|
data-toggle="tooltip"
|
||||||
>
|
>
|
||||||
@ -168,7 +168,7 @@ exports[`Nav component is displaying 1`] = `
|
|||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
class=" nav-item"
|
class="nav-item"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="btn btn-plain nav-link"
|
class="btn btn-plain nav-link"
|
||||||
@ -227,7 +227,7 @@ exports[`Nav component is displaying 1`] = `
|
|||||||
/>
|
/>
|
||||||
<line
|
<line
|
||||||
x1="12"
|
x1="12"
|
||||||
x2="12"
|
x2="12.01"
|
||||||
y1="8"
|
y1="8"
|
||||||
y2="8"
|
y2="8"
|
||||||
/>
|
/>
|
||||||
@ -253,11 +253,11 @@ exports[`Nav component is displaying with another configuration and can rerender
|
|||||||
<img
|
<img
|
||||||
alt="Darkwire"
|
alt="Darkwire"
|
||||||
class="logo"
|
class="logo"
|
||||||
src="logo.png"
|
src="/src/img/logo.png"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
class="btn btn-plain btn-link clipboard-trigger room-id ellipsis"
|
class="btn btn-plain btn-link clipboard-trigger room-id ellipsis"
|
||||||
data-clipboard-text="http://localhost/testRoom_2"
|
data-clipboard-text="http://localhost:3000/testRoom_2"
|
||||||
data-placement="bottom"
|
data-placement="bottom"
|
||||||
data-toggle="tooltip"
|
data-toggle="tooltip"
|
||||||
>
|
>
|
||||||
@ -456,7 +456,7 @@ exports[`Nav component is displaying with another configuration and can rerender
|
|||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
class=" nav-item"
|
class="nav-item"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="btn btn-plain nav-link"
|
class="btn btn-plain nav-link"
|
||||||
@ -515,7 +515,7 @@ exports[`Nav component is displaying with another configuration and can rerender
|
|||||||
/>
|
/>
|
||||||
<line
|
<line
|
||||||
x1="12"
|
x1="12"
|
||||||
x2="12"
|
x2="12.01"
|
||||||
y1="8"
|
y1="8"
|
||||||
y2="8"
|
y2="8"
|
||||||
/>
|
/>
|
@ -1,13 +1,14 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import shortId from 'shortid';
|
import { nanoid } from 'nanoid';
|
||||||
import { Info, Settings, PlusCircle, User, Users, Lock, Unlock, Star } from 'react-feather';
|
import { Info, Settings, PlusCircle, User, Users, Lock, Unlock, Star } from 'react-feather';
|
||||||
import logoImg from 'img/logo.png';
|
|
||||||
import Dropdown, { DropdownTrigger, DropdownContent } from 'react-simple-dropdown';
|
import Dropdown, { DropdownTrigger, DropdownContent } from 'react-simple-dropdown';
|
||||||
import Username from 'components/Username';
|
|
||||||
import Clipboard from 'clipboard';
|
import Clipboard from 'clipboard';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
import logoImg from '@/img/logo.png';
|
||||||
|
import Username from '@/components/Username';
|
||||||
|
|
||||||
class Nav extends Component {
|
class Nav extends Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const clip = new Clipboard('.clipboard-trigger');
|
const clip = new Clipboard('.clipboard-trigger');
|
||||||
@ -38,7 +39,7 @@ class Nav extends Component {
|
|||||||
|
|
||||||
newRoom() {
|
newRoom() {
|
||||||
$('.navbar-collapse').collapse('hide');
|
$('.navbar-collapse').collapse('hide');
|
||||||
window.open(`/${shortId.generate()}`);
|
window.open(`/${nanoid()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSettingsClick() {
|
handleSettingsClick() {
|
||||||
@ -138,10 +139,7 @@ class Nav extends Component {
|
|||||||
<PlusCircle /> <span>{this.props.translations.newRoomButton}</span>
|
<PlusCircle /> <span>{this.props.translations.newRoomButton}</span>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li className="nav-item">
|
||||||
className="
|
|
||||||
nav-item"
|
|
||||||
>
|
|
||||||
<button onClick={this.handleSettingsClick.bind(this)} className="btn btn-plain nav-link">
|
<button onClick={this.handleSettingsClick.bind(this)} className="btn btn-plain nav-link">
|
||||||
<Settings /> <span>{this.props.translations.settingsButton}</span>
|
<Settings /> <span>{this.props.translations.settingsButton}</span>
|
||||||
</button>
|
</button>
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import Notice from '.';
|
import Notice from '.';
|
||||||
|
import { test, expect } from 'vitest';
|
||||||
|
|
||||||
test('Notice component is displaying', async () => {
|
test('Notice component is displaying', async () => {
|
||||||
const { asFragment } = render(
|
const { asFragment } = render(
|
@ -1,4 +1,4 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`Notice component is displaying 1`] = `
|
exports[`Notice component is displaying 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
@ -2,24 +2,24 @@ import React from 'react';
|
|||||||
import { render, fireEvent } from '@testing-library/react';
|
import { render, fireEvent } from '@testing-library/react';
|
||||||
import RoomLink from '.';
|
import RoomLink from '.';
|
||||||
import mock$ from 'jquery';
|
import mock$ from 'jquery';
|
||||||
|
import { describe, it, expect, vi, afterEach } from 'vitest';
|
||||||
|
|
||||||
const mockTooltip = jest.fn().mockImplementation(param => {
|
const mockTooltip = vi.fn().mockImplementation(param => {});
|
||||||
// console.log('tooltip', param);
|
|
||||||
|
vi.mock('jquery', () => {
|
||||||
|
return {
|
||||||
|
default: vi.fn().mockImplementation(param => {
|
||||||
|
if (typeof param === 'function') {
|
||||||
|
param();
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
tooltip: mockTooltip,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('jquery', () => {
|
vi.useFakeTimers();
|
||||||
return jest.fn().mockImplementation(param => {
|
|
||||||
// console.log('$', param);
|
|
||||||
if (typeof param === 'function') {
|
|
||||||
param();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
tooltip: mockTooltip,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.useFakeTimers();
|
|
||||||
|
|
||||||
const mockTranslations = {
|
const mockTranslations = {
|
||||||
copyButtonTooltip: 'copyButton',
|
copyButtonTooltip: 'copyButton',
|
||||||
@ -47,11 +47,11 @@ describe('RoomLink', () => {
|
|||||||
|
|
||||||
it('should copy link', async () => {
|
it('should copy link', async () => {
|
||||||
// Mock execCommand for paste
|
// Mock execCommand for paste
|
||||||
document.execCommand = jest.fn(() => true);
|
document.execCommand = vi.fn(() => true);
|
||||||
|
|
||||||
const { getByTitle } = render(<RoomLink roomId="roomId" translations={mockTranslations} />);
|
const { getByTitle } = render(<RoomLink roomId="roomId" translations={mockTranslations} />);
|
||||||
|
|
||||||
fireEvent.click(getByTitle(mockTranslations.copyButtonTooltip));
|
await fireEvent.click(getByTitle(mockTranslations.copyButtonTooltip));
|
||||||
|
|
||||||
expect(document.execCommand).toHaveBeenLastCalledWith('copy');
|
expect(document.execCommand).toHaveBeenLastCalledWith('copy');
|
||||||
expect(mock$).toHaveBeenCalledTimes(4);
|
expect(mock$).toHaveBeenCalledTimes(4);
|
||||||
@ -59,7 +59,7 @@ describe('RoomLink', () => {
|
|||||||
expect(mockTooltip).toHaveBeenLastCalledWith('show');
|
expect(mockTooltip).toHaveBeenLastCalledWith('show');
|
||||||
|
|
||||||
// Wait for tooltip to close
|
// Wait for tooltip to close
|
||||||
jest.runAllTimers();
|
vi.runAllTimers();
|
||||||
|
|
||||||
expect(mock$).toHaveBeenCalledTimes(6);
|
expect(mock$).toHaveBeenCalledTimes(6);
|
||||||
expect(mock$).toHaveBeenLastCalledWith('.copy-room');
|
expect(mock$).toHaveBeenLastCalledWith('.copy-room');
|
@ -1,6 +1,6 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`RoomLink should display 1`] = `
|
exports[`RoomLink > should display 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<form>
|
<form>
|
||||||
<div
|
<div
|
||||||
@ -14,14 +14,14 @@ exports[`RoomLink should display 1`] = `
|
|||||||
id="room-url"
|
id="room-url"
|
||||||
readonly=""
|
readonly=""
|
||||||
type="text"
|
type="text"
|
||||||
value="http://localhost/roomId"
|
value="http://localhost:3000/roomId"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="input-group-append"
|
class="input-group-append"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="copy-room btn btn-secondary"
|
class="copy-room btn btn-secondary"
|
||||||
data-clipboard-text="http://localhost/roomId"
|
data-clipboard-text="http://localhost:3000/roomId"
|
||||||
data-placement="bottom"
|
data-placement="bottom"
|
||||||
data-toggle="tooltip"
|
data-toggle="tooltip"
|
||||||
title="copyButton"
|
title="copyButton"
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import RoomLocked from '.';
|
import RoomLocked from '.';
|
||||||
|
import { test, expect } from 'vitest';
|
||||||
|
|
||||||
test('RoomLocked component should display', () => {
|
test('RoomLocked component should display', () => {
|
||||||
const { asFragment } = render(<RoomLocked modalContent={'test'} />);
|
const { asFragment } = render(<RoomLocked modalContent={'test'} />);
|
@ -1,4 +1,4 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`RoomLocked component should display 1`] = `
|
exports[`RoomLocked component should display 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
@ -1,7 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, fireEvent, waitFor } from '@testing-library/react';
|
import { render, fireEvent, waitFor } from '@testing-library/react';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import configureStore from 'store';
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
|
|
||||||
|
import configureStore from '@/store';
|
||||||
|
|
||||||
import Settings from '.';
|
import Settings from '.';
|
||||||
|
|
||||||
@ -11,9 +13,24 @@ const mockTranslations = {
|
|||||||
sound: 'soundCheck',
|
sound: 'soundCheck',
|
||||||
};
|
};
|
||||||
|
|
||||||
jest.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
|
|
||||||
jest.mock('components/RoomLink');
|
vi.mock('@/components/RoomLink');
|
||||||
|
|
||||||
|
const mockTooltip = vi.fn().mockImplementation(param => {});
|
||||||
|
|
||||||
|
vi.mock('jquery', () => {
|
||||||
|
return {
|
||||||
|
default: vi.fn().mockImplementation(param => {
|
||||||
|
if (typeof param === 'function') {
|
||||||
|
param();
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
tooltip: mockTooltip,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
describe('Settings component', () => {
|
describe('Settings component', () => {
|
||||||
it('should display', async () => {
|
it('should display', async () => {
|
||||||
@ -24,7 +41,7 @@ describe('Settings component', () => {
|
|||||||
toggleSoundEnabled={() => {}}
|
toggleSoundEnabled={() => {}}
|
||||||
notificationIsEnabled={true}
|
notificationIsEnabled={true}
|
||||||
toggleNotificationEnabled={() => {}}
|
toggleNotificationEnabled={() => {}}
|
||||||
toggleNotificationAllowed={jest.fn()}
|
toggleNotificationAllowed={vi.fn()}
|
||||||
roomId="roomId"
|
roomId="roomId"
|
||||||
setLanguage={() => {}}
|
setLanguage={() => {}}
|
||||||
translations={{}}
|
translations={{}}
|
||||||
@ -42,7 +59,7 @@ describe('Settings component', () => {
|
|||||||
notificationIsEnabled={true}
|
notificationIsEnabled={true}
|
||||||
notificationIsAllowed={false}
|
notificationIsAllowed={false}
|
||||||
toggleNotificationEnabled={() => {}}
|
toggleNotificationEnabled={() => {}}
|
||||||
toggleNotificationAllowed={jest.fn()}
|
toggleNotificationAllowed={vi.fn()}
|
||||||
roomId="roomId"
|
roomId="roomId"
|
||||||
setLanguage={() => {}}
|
setLanguage={() => {}}
|
||||||
translations={{}}
|
translations={{}}
|
||||||
@ -54,7 +71,7 @@ describe('Settings component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should toggle sound', async () => {
|
it('should toggle sound', async () => {
|
||||||
const toggleSound = jest.fn();
|
const toggleSound = vi.fn();
|
||||||
const { getByText } = render(
|
const { getByText } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Settings
|
<Settings
|
||||||
@ -63,7 +80,7 @@ describe('Settings component', () => {
|
|||||||
notificationIsEnabled={true}
|
notificationIsEnabled={true}
|
||||||
notificationIsAllowed={true}
|
notificationIsAllowed={true}
|
||||||
toggleNotificationEnabled={() => {}}
|
toggleNotificationEnabled={() => {}}
|
||||||
toggleNotificationAllowed={jest.fn()}
|
toggleNotificationAllowed={vi.fn()}
|
||||||
roomId="roomId"
|
roomId="roomId"
|
||||||
setLanguage={() => {}}
|
setLanguage={() => {}}
|
||||||
translations={{}}
|
translations={{}}
|
||||||
@ -79,10 +96,10 @@ describe('Settings component', () => {
|
|||||||
|
|
||||||
it('should toggle notifications', async () => {
|
it('should toggle notifications', async () => {
|
||||||
global.Notification = {
|
global.Notification = {
|
||||||
requestPermission: jest.fn().mockResolvedValue('granted'),
|
requestPermission: vi.fn().mockResolvedValue('granted'),
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleNotifications = jest.fn();
|
const toggleNotifications = vi.fn();
|
||||||
const { getByText } = render(
|
const { getByText } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Settings
|
<Settings
|
||||||
@ -91,7 +108,7 @@ describe('Settings component', () => {
|
|||||||
notificationIsEnabled={true}
|
notificationIsEnabled={true}
|
||||||
notificationIsAllowed={true}
|
notificationIsAllowed={true}
|
||||||
toggleNotificationEnabled={toggleNotifications}
|
toggleNotificationEnabled={toggleNotifications}
|
||||||
toggleNotificationAllowed={jest.fn()}
|
toggleNotificationAllowed={vi.fn()}
|
||||||
roomId="roomId"
|
roomId="roomId"
|
||||||
setLanguage={() => {}}
|
setLanguage={() => {}}
|
||||||
translations={{}}
|
translations={{}}
|
||||||
@ -101,7 +118,7 @@ describe('Settings component', () => {
|
|||||||
|
|
||||||
fireEvent.click(getByText('Desktop Notification'));
|
fireEvent.click(getByText('Desktop Notification'));
|
||||||
|
|
||||||
jest.runAllTimers();
|
vi.runAllTimers();
|
||||||
|
|
||||||
delete global.Notification;
|
delete global.Notification;
|
||||||
|
|
||||||
@ -110,11 +127,11 @@ describe('Settings component', () => {
|
|||||||
|
|
||||||
it('should not toggle notifications', async () => {
|
it('should not toggle notifications', async () => {
|
||||||
global.Notification = {
|
global.Notification = {
|
||||||
requestPermission: jest.fn().mockResolvedValue('denied'),
|
requestPermission: vi.fn().mockResolvedValue('denied'),
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleNotifications = jest.fn();
|
const toggleNotifications = vi.fn();
|
||||||
const toggleAllowed = jest.fn();
|
const toggleAllowed = vi.fn();
|
||||||
const { getByText } = render(
|
const { getByText } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Settings
|
<Settings
|
||||||
@ -133,7 +150,7 @@ describe('Settings component', () => {
|
|||||||
|
|
||||||
fireEvent.click(getByText('Desktop Notification'));
|
fireEvent.click(getByText('Desktop Notification'));
|
||||||
|
|
||||||
jest.runAllTimers();
|
vi.runAllTimers();
|
||||||
|
|
||||||
delete global.Notification;
|
delete global.Notification;
|
||||||
|
|
||||||
@ -142,7 +159,7 @@ describe('Settings component', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should change lang', async () => {
|
it('should change lang', async () => {
|
||||||
const changeLang = jest.fn();
|
const changeLang = vi.fn();
|
||||||
|
|
||||||
const { getByDisplayValue } = render(
|
const { getByDisplayValue } = render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
@ -151,7 +168,7 @@ describe('Settings component', () => {
|
|||||||
toggleSoundEnabled={() => {}}
|
toggleSoundEnabled={() => {}}
|
||||||
notificationIsEnabled={true}
|
notificationIsEnabled={true}
|
||||||
toggleNotificationEnabled={() => {}}
|
toggleNotificationEnabled={() => {}}
|
||||||
toggleNotificationAllowed={jest.fn()}
|
toggleNotificationAllowed={vi.fn()}
|
||||||
roomId="roomId"
|
roomId="roomId"
|
||||||
setLanguage={changeLang}
|
setLanguage={changeLang}
|
||||||
translations={{}}
|
translations={{}}
|
@ -1,9 +1,9 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`Settings component should display 1`] = `
|
exports[`Settings component > should display 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div
|
<div
|
||||||
class="styles"
|
class="_styles_23b490"
|
||||||
>
|
>
|
||||||
<section>
|
<section>
|
||||||
<h4>
|
<h4>
|
||||||
@ -127,6 +127,11 @@ exports[`Settings component should display 1`] = `
|
|||||||
>
|
>
|
||||||
Türkçe
|
Türkçe
|
||||||
</option>
|
</option>
|
||||||
|
<option
|
||||||
|
value="ko"
|
||||||
|
>
|
||||||
|
한국어
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@ -192,10 +197,10 @@ exports[`Settings component should display 1`] = `
|
|||||||
</DocumentFragment>
|
</DocumentFragment>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Settings component should display 2`] = `
|
exports[`Settings component > should display 2`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
||||||
<div
|
<div
|
||||||
class="styles"
|
class="_styles_23b490"
|
||||||
>
|
>
|
||||||
<section>
|
<section>
|
||||||
<h4>
|
<h4>
|
||||||
@ -313,6 +318,11 @@ exports[`Settings component should display 2`] = `
|
|||||||
>
|
>
|
||||||
Türkçe
|
Türkçe
|
||||||
</option>
|
</option>
|
||||||
|
<option
|
||||||
|
value="ko"
|
||||||
|
>
|
||||||
|
한국어
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
@ -1,9 +1,11 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import RoomLink from 'components/RoomLink';
|
|
||||||
import { styles } from './styles.module.scss';
|
|
||||||
import Cookie from 'js-cookie';
|
import Cookie from 'js-cookie';
|
||||||
import T from 'components/T';
|
|
||||||
|
import RoomLink from '@/components/RoomLink';
|
||||||
|
import T from '@/components/T';
|
||||||
|
|
||||||
|
import classes from './styles.module.scss';
|
||||||
|
|
||||||
class Settings extends Component {
|
class Settings extends Component {
|
||||||
handleSoundToggle() {
|
handleSoundToggle() {
|
||||||
@ -30,7 +32,7 @@ class Settings extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className={styles}>
|
<div className={classes.styles}>
|
||||||
<section>
|
<section>
|
||||||
<h4>
|
<h4>
|
||||||
<T path="newMessageNotification" />
|
<T path="newMessageNotification" />
|
@ -1,8 +1,9 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { getTranslations } from 'i18n';
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import { getTranslations } from '@/i18n';
|
||||||
|
|
||||||
const regex = /{(.*?)}/g;
|
const regex = /{(.*?)}/g;
|
||||||
|
|
||||||
class T extends Component {
|
class T extends Component {
|
@ -1,10 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
|
import { test, expect, vi } from 'vitest';
|
||||||
|
|
||||||
import T from './T';
|
import T from './T';
|
||||||
|
|
||||||
// To avoid missing provider
|
// To avoid missing provider
|
||||||
jest.mock('components/T');
|
vi.mock('components/T');
|
||||||
|
|
||||||
test('T component is displaying', async () => {
|
test('T component is displaying', async () => {
|
||||||
const { asFragment, rerender } = render(<T path="welcomeHeader" language="en" />);
|
const { asFragment, rerender } = render(<T path="welcomeHeader" language="en" />);
|
@ -1,4 +1,4 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`T component is displaying 1`] = `
|
exports[`T component is displaying 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
@ -1,5 +1,5 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import T from 'components/T/T';
|
import T from './T';
|
||||||
|
|
||||||
export default connect((state, ownProps) => ({
|
export default connect((state, ownProps) => ({
|
||||||
language: state.app.language,
|
language: state.app.language,
|
@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
|
import { test, expect } from 'vitest';
|
||||||
|
|
||||||
import Username from '.';
|
import Username from '.';
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
exports[`Username component is displaying 1`] = `
|
exports[`Username component is displaying 1`] = `
|
||||||
<DocumentFragment>
|
<DocumentFragment>
|
@ -1,8 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
|
import { test, expect, vi } from 'vitest';
|
||||||
|
|
||||||
import Welcome from '.';
|
import Welcome from '.';
|
||||||
|
|
||||||
|
vi.mock('@/components/RoomLink');
|
||||||
|
|
||||||
test('Welcome component is displaying', async () => {
|
test('Welcome component is displaying', async () => {
|
||||||
const { asFragment } = render(<Welcome roomId="roomtest" close={() => {}} translations={{}} />);
|
const { asFragment } = render(<Welcome roomId="roomtest" close={() => {}} translations={{}} />);
|
||||||
|
|
@ -1,106 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`Welcome component is displaying 1`] = `
|
|
||||||
<DocumentFragment>
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
v2.0 is a complete rewrite and includes several new features. Here are some highlights:
|
|
||||||
<ul
|
|
||||||
class="native"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
Support on all modern browsers (Chrome, Firefox, Safari, Safari iOS, Android)
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Slash commands (/nick, /me, /clear)
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Room owners can lock the room, preventing anyone else from joining
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Front-end rewritten in React.js and Redux
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Send files up to 4 MB
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<div>
|
|
||||||
You can learn more
|
|
||||||
<a
|
|
||||||
href="https://github.com/darkwire/darkwire.io"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
here
|
|
||||||
</a>
|
|
||||||
.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br />
|
|
||||||
<p
|
|
||||||
class="mb-2"
|
|
||||||
>
|
|
||||||
Others can join this room using the following URL:
|
|
||||||
</p>
|
|
||||||
<form>
|
|
||||||
<div
|
|
||||||
class="form-group"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="input-group"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
class="form-control"
|
|
||||||
id="room-url"
|
|
||||||
readonly=""
|
|
||||||
type="text"
|
|
||||||
value="http://localhost/roomtest"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="input-group-append"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="copy-room btn btn-secondary"
|
|
||||||
data-clipboard-text="http://localhost/roomtest"
|
|
||||||
data-placement="bottom"
|
|
||||||
data-toggle="tooltip"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
fill="none"
|
|
||||||
height="24"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<rect
|
|
||||||
height="13"
|
|
||||||
rx="2"
|
|
||||||
ry="2"
|
|
||||||
width="13"
|
|
||||||
x="9"
|
|
||||||
y="9"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<div
|
|
||||||
class="react-modal-footer"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="btn btn-primary btn-lg"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</DocumentFragment>
|
|
||||||
`;
|
|
@ -0,0 +1,54 @@
|
|||||||
|
// Vitest Snapshot v1
|
||||||
|
|
||||||
|
exports[`Welcome component is displaying 1`] = `
|
||||||
|
<DocumentFragment>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
v2.0 is a complete rewrite and includes several new features. Here are some highlights:
|
||||||
|
<ul
|
||||||
|
class="native"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
Support on all modern browsers (Chrome, Firefox, Safari, Safari iOS, Android)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Slash commands (/nick, /me, /clear)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Room owners can lock the room, preventing anyone else from joining
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Front-end rewritten in React.js and Redux
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Send files up to 4 MB
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div>
|
||||||
|
You can learn more
|
||||||
|
<a
|
||||||
|
href="https://github.com/darkwire/darkwire.io"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
here
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<p
|
||||||
|
class="mb-2"
|
||||||
|
>
|
||||||
|
Others can join this room using the following URL:
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
class="react-modal-footer"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="btn btn-primary btn-lg"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DocumentFragment>
|
||||||
|
`;
|
@ -1,6 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import RoomLink from 'components/RoomLink';
|
import RoomLink from '@/components/RoomLink';
|
||||||
|
|
||||||
class Welcome extends Component {
|
class Welcome extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
@ -1,2 +1,5 @@
|
|||||||
/* istanbul ignore file */
|
/* istanbul ignore file */
|
||||||
export default process.env.NODE_ENV;
|
export const MAX_FILE_SIZE = import.meta.VITE_MAX_FILE_SIZE || 4;
|
||||||
|
export const COMMIT_SHA = import.meta.env.VITE_COMMIT_SHA;
|
||||||
|
|
||||||
|
export default import.meta.env.NODE_ENV;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { getTranslations } from './index.js';
|
import { getTranslations } from './';
|
||||||
|
|
||||||
|
import { test, expect } from 'vitest';
|
||||||
|
|
||||||
test('Get translation', () => {
|
test('Get translation', () => {
|
||||||
expect(getTranslations('en').welcomeHeader).toBe('Welcome to Darkwire v2.0');
|
expect(getTranslations('en').welcomeHeader).toBe('Welcome to Darkwire v2.0');
|
||||||
|
@ -34,11 +34,11 @@ const languagesMap = {
|
|||||||
export function getTranslations(language = '') {
|
export function getTranslations(language = '') {
|
||||||
const [lang, variant] = language.split('-');
|
const [lang, variant] = language.split('-');
|
||||||
|
|
||||||
if (languagesMap.hasOwnProperty(`${lang}${variant}`)) {
|
if (Object.prototype.hasOwnProperty.call(languagesMap, `${lang}${variant}`)) {
|
||||||
return languagesMap[`${lang}${variant}`];
|
return languagesMap[`${lang}${variant}`];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (languagesMap.hasOwnProperty(lang)) {
|
if (Object.prototype.hasOwnProperty.call(languagesMap, `${lang}`)) {
|
||||||
return languagesMap[lang];
|
return languagesMap[lang];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
/* istanbul ignore file */
|
|
||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import './index.css';
|
|
||||||
import Root from './root';
|
|
||||||
import * as serviceWorker from './serviceWorker';
|
|
||||||
|
|
||||||
ReactDOM.render(<Root />, document.getElementById('root'));
|
|
||||||
|
|
||||||
// If you want your app to work offline and load faster, you can change
|
|
||||||
// unregister() to register() below. Note this comes with some pitfalls.
|
|
||||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
|
||||||
serviceWorker.unregister();
|
|
@ -1,5 +0,0 @@
|
|||||||
describe('Timezones', () => {
|
|
||||||
it('should always be UTC', () => {
|
|
||||||
expect(new Date().getTimezoneOffset()).toBe(0);
|
|
||||||
});
|
|
||||||
});
|
|
52
client/src/main.tsx
Normal file
52
client/src/main.tsx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
import { nanoid } from 'nanoid';
|
||||||
|
import { createBrowserRouter, RouterProvider, Navigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
|
import 'react-simple-dropdown/styles/Dropdown.css';
|
||||||
|
import './stylesheets/app.sass';
|
||||||
|
import 'bootstrap/dist/js/bootstrap.bundle.min.js';
|
||||||
|
|
||||||
|
import configureStore from '@/store/';
|
||||||
|
import Home from '@/components/Home/';
|
||||||
|
import { hasTouchSupport } from '@/utils/dom';
|
||||||
|
|
||||||
|
const store = configureStore();
|
||||||
|
|
||||||
|
const router = createBrowserRouter([
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
element: <Navigate to={`/${nanoid()}`} replace />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/:roomId',
|
||||||
|
element: <Home />,
|
||||||
|
loader({ params }) {
|
||||||
|
return encodeURI(params.roomId ? params.roomId : '');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const Main = () => {
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (hasTouchSupport) {
|
||||||
|
document.body.classList.add('touch');
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Provider store={store}>
|
||||||
|
<RouterProvider router={router} />
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const root = createRoot(document.getElementById('root') as HTMLElement);
|
||||||
|
|
||||||
|
root.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<Main />
|
||||||
|
</React.StrictMode>,
|
||||||
|
);
|
@ -76,10 +76,7 @@ const activities = (state = initialState, action) => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
case 'RECEIVE_ENCRYPTED_MESSAGE_ADD_USER':
|
case 'RECEIVE_ENCRYPTED_MESSAGE_ADD_USER':
|
||||||
const newUserId = action.payload.payload.id;
|
if (action.payload.state.room.members.find(m => m.id === action.payload.payload.id)) {
|
||||||
|
|
||||||
const haveUser = action.payload.state.room.members.find(m => m.id === newUserId);
|
|
||||||
if (haveUser) {
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +85,7 @@ const activities = (state = initialState, action) => {
|
|||||||
items: [
|
items: [
|
||||||
...state.items,
|
...state.items,
|
||||||
{
|
{
|
||||||
userId: newUserId,
|
userId: action.payload.payload.id,
|
||||||
type: 'USER_ENTER',
|
type: 'USER_ENTER',
|
||||||
username: action.payload.payload.username,
|
username: action.payload.payload.username,
|
||||||
},
|
},
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
|
||||||
import reducer from './activities';
|
import reducer from './activities';
|
||||||
|
|
||||||
describe('Activities reducer', () => {
|
describe('Activities reducer', () => {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import Cookie from 'js-cookie';
|
import Cookie from 'js-cookie';
|
||||||
import { getTranslations } from 'i18n';
|
|
||||||
|
import { getTranslations } from '@/i18n';
|
||||||
|
|
||||||
const language = Cookie.get('language') || navigator.language || 'en';
|
const language = Cookie.get('language') || navigator.language || 'en';
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import reducer from './app';
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
import { getTranslations } from 'i18n';
|
|
||||||
|
|
||||||
jest.mock('i18n', () => {
|
import reducer from './app';
|
||||||
|
import { getTranslations } from '@/i18n';
|
||||||
|
|
||||||
|
vi.mock('@/i18n', () => {
|
||||||
return {
|
return {
|
||||||
getTranslations: jest.fn().mockReturnValue({ path: 'test' }),
|
getTranslations: vi.fn().mockReturnValue({ path: 'test' }),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* istanbul ignore file */
|
/* istanbul ignore file */
|
||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
|
|
||||||
import app from './app';
|
import app from './app';
|
||||||
import activities from './activities';
|
import activities from './activities';
|
||||||
import user from './user';
|
import user from './user';
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable no-case-declarations */
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
|
||||||
import reducer from './room';
|
import reducer from './room';
|
||||||
|
|
||||||
describe('Room reducer', () => {
|
describe('Room reducer', () => {
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
|
|
||||||
import reducer from './user';
|
import reducer from './user';
|
||||||
|
|
||||||
jest.mock('i18n', () => {
|
vi.mock('@/i18n', () => {
|
||||||
return {
|
return {
|
||||||
getTranslations: jest.fn().mockReturnValue({ path: 'test' }),
|
getTranslations: vi.fn().mockReturnValue({ path: 'test' }),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import 'bootstrap/dist/js/bootstrap.bundle.min.js';
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Redirect } from 'react-router';
|
import { Redirect } from 'react-router';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import configureStore from 'store';
|
import configureStore from './store';
|
||||||
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
||||||
import shortId from 'shortid';
|
import shortId from 'shortid';
|
||||||
import Home from 'components/Home';
|
import Home from 'components/Home';
|
@ -20,9 +20,9 @@ const isLocalhost = Boolean(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export function register(config) {
|
export function register(config) {
|
||||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
if (import.meta.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||||
// The URL constructor is available in all browsers that support SW.
|
// The URL constructor is available in all browsers that support SW.
|
||||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
const publicUrl = new URL(import.meta.env.PUBLIC_URL, window.location.href);
|
||||||
if (publicUrl.origin !== window.location.origin) {
|
if (publicUrl.origin !== window.location.origin) {
|
||||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||||
// from what our page is served on. This might happen if a CDN is used to
|
// from what our page is served on. This might happen if a CDN is used to
|
||||||
@ -31,7 +31,7 @@ export function register(config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
const swUrl = `${import.meta.env.PUBLIC_URL}/service-worker.js`;
|
||||||
|
|
||||||
if (isLocalhost) {
|
if (isLocalhost) {
|
||||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
import { configure } from 'enzyme';
|
import { expect, afterEach, vi } from 'vitest';
|
||||||
import Adapter from 'enzyme-adapter-react-16';
|
import { cleanup } from '@testing-library/react';
|
||||||
// this adds jest-dom's custom assertions
|
import matchers from '@testing-library/jest-dom/extend-expect';
|
||||||
import '@testing-library/jest-dom/extend-expect';
|
import createFetchMock from 'vitest-fetch-mock';
|
||||||
import { enableFetchMocks } from 'jest-fetch-mock';
|
|
||||||
|
|
||||||
configure({ adapter: new Adapter() });
|
const fetchMock = createFetchMock(vi);
|
||||||
enableFetchMocks();
|
fetchMock.enableMocks();
|
||||||
|
|
||||||
|
expect.extend(matchers);
|
||||||
|
|
||||||
|
// runs a cleanup after each test case (e.g. clearing jsdom)
|
||||||
|
afterEach(() => {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
/* istanbul ignore file */
|
/* istanbul ignore file */
|
||||||
import { createStore, applyMiddleware, compose } from 'redux';
|
import { createStore, applyMiddleware, compose } from 'redux';
|
||||||
import reducers from 'reducers';
|
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
|
|
||||||
|
import reducers from '@/reducers';
|
||||||
|
|
||||||
const composeEnhancers =
|
const composeEnhancers =
|
||||||
process.env.NODE_ENV === 'production' ? compose : window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
import.meta.env.NODE_ENV === 'production' ? compose : window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
||||||
|
|
||||||
const enabledMiddlewares = [thunk];
|
const enabledMiddlewares = [thunk];
|
||||||
|
|
||||||
@ -12,14 +13,5 @@ const middlewares = applyMiddleware(...enabledMiddlewares);
|
|||||||
|
|
||||||
export default function configureStore(preloadedState) {
|
export default function configureStore(preloadedState) {
|
||||||
const store = createStore(reducers, preloadedState, composeEnhancers(middlewares));
|
const store = createStore(reducers, preloadedState, composeEnhancers(middlewares));
|
||||||
|
|
||||||
if (module.hot) {
|
|
||||||
module.hot.accept('../reducers', () => {
|
|
||||||
// eslint-disable-next-line global-require
|
|
||||||
const nextRootReducer = require('../reducers/index');
|
|
||||||
store.replaceReducer(nextRootReducer);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
/* istanbul ignore file */
|
|
||||||
import Enzyme from 'enzyme';
|
|
||||||
import Adapter from 'enzyme-adapter-react-16';
|
|
||||||
|
|
||||||
Enzyme.configure({ adapter: new Adapter() });
|
|
@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable import/prefer-default-export */
|
|
||||||
export const getSelectedText = () => {
|
export const getSelectedText = () => {
|
||||||
let text = '';
|
let text = '';
|
||||||
if (typeof window.getSelection !== 'undefined') {
|
if (typeof window.getSelection !== 'undefined') {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable import/prefer-default-export */
|
|
||||||
export const getObjectUrl = (encodedFile, fileType) => {
|
export const getObjectUrl = (encodedFile, fileType) => {
|
||||||
const b64 = unescape(encodedFile);
|
const b64 = unescape(encodedFile);
|
||||||
const sliceSize = 1024;
|
const sliceSize = 1024;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable import/prefer-default-export */
|
|
||||||
export function sanitize(str) {
|
export function sanitize(str) {
|
||||||
return str.replace(/[^A-Za-z0-9._]/g, '-').replace(/[<>]/gi, '');
|
return str.replace(/[^A-Za-z0-9._]/g, '-').replace(/[<>]/gi, '');
|
||||||
}
|
}
|
||||||
|
@ -2,112 +2,107 @@ import Crypto from './crypto';
|
|||||||
|
|
||||||
const crypto = new Crypto();
|
const crypto = new Crypto();
|
||||||
|
|
||||||
export const process = (payload, state) =>
|
export const process = async (payload, state) => {
|
||||||
new Promise(async (resolve, reject) => {
|
const privateKeyJson = state.user.privateKey;
|
||||||
const privateKeyJson = state.user.privateKey;
|
const privateKey = await crypto.importEncryptDecryptKey(privateKeyJson, 'jwk', ['decrypt', 'unwrapKey']);
|
||||||
const privateKey = await crypto.importEncryptDecryptKey(privateKeyJson, 'jwk', ['decrypt', 'unwrapKey']);
|
|
||||||
|
|
||||||
let sessionKey;
|
const iv = await crypto.convertStringToArrayBufferView(payload.iv);
|
||||||
let signingKey;
|
const signature = await crypto.convertStringToArrayBufferView(payload.signature);
|
||||||
|
const payloadBuffer = await crypto.convertStringToArrayBufferView(payload.payload);
|
||||||
|
|
||||||
const iv = await crypto.convertStringToArrayBufferView(payload.iv);
|
// We try to decrypt all sessions and signin keys to get the one encrypted for self
|
||||||
const signature = await crypto.convertStringToArrayBufferView(payload.signature);
|
const [sessionKey, signingKey] = await new Promise(resolvePayload => {
|
||||||
const payloadBuffer = await crypto.convertStringToArrayBufferView(payload.payload);
|
payload.keys.forEach(async key => {
|
||||||
|
try {
|
||||||
|
const sessionKey = await crypto.unwrapKey(
|
||||||
|
'jwk',
|
||||||
|
key.sessionKey,
|
||||||
|
privateKey,
|
||||||
|
{
|
||||||
|
name: 'RSA-OAEP',
|
||||||
|
hash: { name: 'SHA-1' },
|
||||||
|
},
|
||||||
|
{ name: 'AES-CBC' },
|
||||||
|
true,
|
||||||
|
['decrypt'],
|
||||||
|
);
|
||||||
|
|
||||||
await new Promise(resolvePayload => {
|
const signingKey = await crypto.unwrapKey(
|
||||||
payload.keys.forEach(async key => {
|
'jwk',
|
||||||
try {
|
key.signingKey,
|
||||||
sessionKey = await crypto.unwrapKey(
|
privateKey,
|
||||||
'jwk',
|
{
|
||||||
key.sessionKey,
|
name: 'RSA-OAEP',
|
||||||
privateKey,
|
hash: { name: 'SHA-1' },
|
||||||
{
|
},
|
||||||
name: 'RSA-OAEP',
|
{ name: 'HMAC', hash: { name: 'SHA-256' } },
|
||||||
hash: { name: 'SHA-1' },
|
true,
|
||||||
},
|
['verify'],
|
||||||
{ name: 'AES-CBC' },
|
);
|
||||||
true,
|
resolvePayload([sessionKey, signingKey]);
|
||||||
['decrypt'],
|
} catch (e) {} // eslint-disable-line
|
||||||
);
|
|
||||||
|
|
||||||
signingKey = await crypto.unwrapKey(
|
|
||||||
'jwk',
|
|
||||||
key.signingKey,
|
|
||||||
privateKey,
|
|
||||||
{
|
|
||||||
name: 'RSA-OAEP',
|
|
||||||
hash: { name: 'SHA-1' },
|
|
||||||
},
|
|
||||||
{ name: 'HMAC', hash: { name: 'SHA-256' } },
|
|
||||||
true,
|
|
||||||
['verify'],
|
|
||||||
);
|
|
||||||
resolvePayload();
|
|
||||||
} catch (e) {} // eslint-disable-line
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const verified = await crypto.verifyPayload(signature, payloadBuffer, signingKey);
|
|
||||||
|
|
||||||
if (!verified) {
|
|
||||||
reject();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const decryptedPayload = await crypto.decryptMessage(payloadBuffer, sessionKey, iv);
|
|
||||||
|
|
||||||
const payloadJson = JSON.parse(crypto.convertArrayBufferViewToString(new Uint8Array(decryptedPayload)));
|
|
||||||
|
|
||||||
resolve(payloadJson);
|
|
||||||
});
|
|
||||||
|
|
||||||
export const prepare = (payload, state) =>
|
|
||||||
new Promise(async resolve => {
|
|
||||||
const myUsername = state.user.username;
|
|
||||||
const myId = state.user.id;
|
|
||||||
|
|
||||||
const sessionKey = await crypto.createSecretKey();
|
|
||||||
const signingKey = await crypto.createSigningKey();
|
|
||||||
const iv = await crypto.crypto.getRandomValues(new Uint8Array(16));
|
|
||||||
|
|
||||||
const jsonToSend = {
|
|
||||||
...payload,
|
|
||||||
payload: {
|
|
||||||
...payload.payload,
|
|
||||||
sender: myId,
|
|
||||||
username: myUsername,
|
|
||||||
text: encodeURI(payload.payload.text),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const payloadBuffer = crypto.convertStringToArrayBufferView(JSON.stringify(jsonToSend));
|
|
||||||
|
|
||||||
const encryptedPayload = await crypto.encryptMessage(payloadBuffer, sessionKey, iv);
|
|
||||||
const payloadString = await crypto.convertArrayBufferViewToString(new Uint8Array(encryptedPayload));
|
|
||||||
|
|
||||||
const signature = await crypto.signMessage(encryptedPayload, signingKey);
|
|
||||||
|
|
||||||
const encryptedKeys = await Promise.all(
|
|
||||||
state.room.members.map(async member => {
|
|
||||||
const key = await crypto.importEncryptDecryptKey(member.publicKey);
|
|
||||||
const enc = await Promise.all([crypto.wrapKey(sessionKey, key), crypto.wrapKey(signingKey, key)]);
|
|
||||||
return {
|
|
||||||
sessionKey: enc[0],
|
|
||||||
signingKey: enc[1],
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const ivString = await crypto.convertArrayBufferViewToString(new Uint8Array(iv));
|
|
||||||
const signatureString = await crypto.convertArrayBufferViewToString(new Uint8Array(signature));
|
|
||||||
|
|
||||||
resolve({
|
|
||||||
toSend: {
|
|
||||||
payload: payloadString,
|
|
||||||
signature: signatureString,
|
|
||||||
iv: ivString,
|
|
||||||
keys: encryptedKeys,
|
|
||||||
},
|
|
||||||
original: jsonToSend,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const verified = await crypto.verifyPayload(signature, payloadBuffer, signingKey);
|
||||||
|
|
||||||
|
if (!verified) {
|
||||||
|
throw new Error("Can't verify message");
|
||||||
|
}
|
||||||
|
|
||||||
|
const decryptedPayload = await crypto.decryptMessage(payloadBuffer, sessionKey, iv);
|
||||||
|
|
||||||
|
const payloadJson = JSON.parse(crypto.convertArrayBufferViewToString(new Uint8Array(decryptedPayload)));
|
||||||
|
|
||||||
|
return payloadJson;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const prepare = async (payload, state) => {
|
||||||
|
const myUsername = state.user.username;
|
||||||
|
const myId = state.user.id;
|
||||||
|
|
||||||
|
const sessionKey = await crypto.createSecretKey();
|
||||||
|
const signingKey = await crypto.createSigningKey();
|
||||||
|
const iv = await crypto.crypto.getRandomValues(new Uint8Array(16));
|
||||||
|
|
||||||
|
const jsonToSend = {
|
||||||
|
...payload,
|
||||||
|
payload: {
|
||||||
|
...payload.payload,
|
||||||
|
sender: myId,
|
||||||
|
username: myUsername,
|
||||||
|
text: encodeURI(payload.payload.text),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const payloadBuffer = crypto.convertStringToArrayBufferView(JSON.stringify(jsonToSend));
|
||||||
|
|
||||||
|
const encryptedPayload = await crypto.encryptMessage(payloadBuffer, sessionKey, iv);
|
||||||
|
const payloadString = await crypto.convertArrayBufferViewToString(new Uint8Array(encryptedPayload));
|
||||||
|
|
||||||
|
const signature = await crypto.signMessage(encryptedPayload, signingKey);
|
||||||
|
|
||||||
|
const encryptedKeys = await Promise.all(
|
||||||
|
state.room.members.map(async member => {
|
||||||
|
const key = await crypto.importEncryptDecryptKey(member.publicKey);
|
||||||
|
const enc = await Promise.all([crypto.wrapKey(sessionKey, key), crypto.wrapKey(signingKey, key)]);
|
||||||
|
return {
|
||||||
|
sessionKey: enc[0],
|
||||||
|
signingKey: enc[1],
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ivString = await crypto.convertArrayBufferViewToString(new Uint8Array(iv));
|
||||||
|
const signatureString = await crypto.convertArrayBufferViewToString(new Uint8Array(signature));
|
||||||
|
|
||||||
|
return {
|
||||||
|
toSend: {
|
||||||
|
payload: payloadString,
|
||||||
|
signature: signatureString,
|
||||||
|
iv: ivString,
|
||||||
|
keys: encryptedKeys,
|
||||||
|
},
|
||||||
|
original: jsonToSend,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import beepFile from 'audio/beep.mp3';
|
import beepFile from '@/audio/beep.mp3';
|
||||||
|
|
||||||
const showNotification = (title, message, avatarUrl) => {
|
const showNotification = (title, message) => {
|
||||||
const notifBody = {
|
const notifBody = {
|
||||||
body: message,
|
body: message,
|
||||||
tag: 'darkwire',
|
tag: 'darkwire',
|
||||||
@ -44,6 +44,21 @@ export const notify = (title, content = '') => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const beep = (window.Audio && new window.Audio(beepFile)) || { play: () => {} };
|
let theBeep;
|
||||||
|
|
||||||
|
export const beep = {
|
||||||
|
async play() {
|
||||||
|
if (window.Audio) {
|
||||||
|
if (theBeep === undefined) {
|
||||||
|
theBeep = new window.Audio(beepFile);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await theBeep.play();
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Can't play sound.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export default { notify, beep };
|
export default { notify, beep };
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import socketIO from 'socket.io-client';
|
import socketIO from 'socket.io-client';
|
||||||
import generateUrl from '../api/generator';
|
import generateUrl from '@/api/generator';
|
||||||
|
|
||||||
let socket;
|
let socket;
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user