-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #631 from systemli/feat/signal-group
✨ Add support to configure Signal group bridge
- Loading branch information
Showing
13 changed files
with
719 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query' | ||
import { render, screen } from '@testing-library/react' | ||
import userEvent from '@testing-library/user-event' | ||
import sign from 'jwt-encode' | ||
import { MemoryRouter } from 'react-router' | ||
import { Ticker } from '../../api/Ticker' | ||
import { AuthProvider } from '../../contexts/AuthContext' | ||
import { NotificationProvider } from '../../contexts/NotificationContext' | ||
import SignalGroupAdminForm from './SignalGroupAdminForm' | ||
|
||
const token = sign({ id: 1, email: '[email protected]', roles: ['user'], exp: new Date().getTime() / 1000 + 600 }, 'secret') | ||
|
||
describe('SignalGroupForm', () => { | ||
beforeAll(() => { | ||
localStorage.setItem('token', token) | ||
}) | ||
|
||
const ticker = ({ active, connected }: { active: boolean; connected: boolean }) => { | ||
return { | ||
id: 1, | ||
signalGroup: { | ||
active: active, | ||
connected: connected, | ||
}, | ||
} as Ticker | ||
} | ||
|
||
const callback = vi.fn() | ||
const setSubmitting = vi.fn() | ||
|
||
beforeEach(() => { | ||
fetchMock.resetMocks() | ||
}) | ||
|
||
function setup(ticker: Ticker) { | ||
const client = new QueryClient({ | ||
defaultOptions: { | ||
queries: { | ||
retry: false, | ||
}, | ||
}, | ||
}) | ||
return render( | ||
<QueryClientProvider client={client}> | ||
<MemoryRouter> | ||
<AuthProvider> | ||
<NotificationProvider> | ||
<div> | ||
<SignalGroupAdminForm callback={callback} ticker={ticker} setSubmitting={setSubmitting} /> | ||
<input name="Submit" type="submit" value="Submit" form="configureSignalGroupAdmin" /> | ||
</div> | ||
</NotificationProvider> | ||
</AuthProvider> | ||
</MemoryRouter> | ||
</QueryClientProvider> | ||
) | ||
} | ||
|
||
it('should render the component', async () => { | ||
setup(ticker({ active: false, connected: false })) | ||
|
||
expect(screen.getByText('Only do this if extra members with write access are needed.')).toBeInTheDocument() | ||
expect(screen.getByRole('textbox', { name: 'Phone number' })).toBeInTheDocument() | ||
|
||
await userEvent.type(screen.getByRole('textbox', { name: 'Phone number' }), '+49123456789') | ||
|
||
fetchMock.mockResponseOnce(JSON.stringify({ status: 'success' })) | ||
|
||
await userEvent.click(screen.getByRole('button', { name: 'Submit' })) | ||
|
||
expect(setSubmitting).toHaveBeenCalledTimes(2) | ||
expect(callback).toHaveBeenCalledTimes(1) | ||
expect(fetchMock).toHaveBeenCalledTimes(1) | ||
expect(fetchMock).toHaveBeenCalledWith('http://localhost:8080/v1/admin/tickers/1/signal_group/admin', { | ||
body: '{"number":"+49123456789"}', | ||
headers: { | ||
Accept: 'application/json', | ||
Authorization: `Bearer ${token}`, | ||
'Content-Type': 'application/json', | ||
}, | ||
method: 'put', | ||
}) | ||
}) | ||
|
||
it('should render the error message', async () => { | ||
setup(ticker({ active: false, connected: false })) | ||
|
||
expect(screen.getByText('Only do this if extra members with write access are needed.')).toBeInTheDocument() | ||
expect(screen.getByRole('textbox', { name: 'Phone number' })).toBeInTheDocument() | ||
|
||
await userEvent.type(screen.getByRole('textbox', { name: 'Phone number' }), '+49123456789') | ||
|
||
fetchMock.mockResponseOnce(JSON.stringify({ status: 'error' }), { status: 400 }) | ||
|
||
await userEvent.click(screen.getByRole('button', { name: 'Submit' })) | ||
|
||
expect(screen.getByText('Failed to add number to Signal group')).toBeInTheDocument() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { faPhone } from '@fortawesome/free-solid-svg-icons' | ||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||
import { Alert, FormGroup, Grid, InputAdornment, TextField } from '@mui/material' | ||
import { FC } from 'react' | ||
import { useForm } from 'react-hook-form' | ||
import { Ticker, TickerSignalGroupAdminFormData, putTickerSignalGroupAdminApi } from '../../api/Ticker' | ||
import useAuth from '../../contexts/useAuth' | ||
import useNotification from '../../contexts/useNotification' | ||
|
||
interface Props { | ||
callback: () => void | ||
ticker: Ticker | ||
setSubmitting: (submitting: boolean) => void | ||
} | ||
|
||
const SignalGroupAdminForm: FC<Props> = ({ callback, ticker, setSubmitting }) => { | ||
const { token } = useAuth() | ||
const { | ||
formState: { errors }, | ||
handleSubmit, | ||
register, | ||
setError, | ||
} = useForm<TickerSignalGroupAdminFormData>() | ||
const { createNotification } = useNotification() | ||
|
||
const onSubmit = handleSubmit(data => { | ||
setSubmitting(true) | ||
putTickerSignalGroupAdminApi(token, data, ticker) | ||
.then(response => { | ||
if (response.status == 'error') { | ||
createNotification({ content: 'Failed to add number to Signal group', severity: 'error' }) | ||
setError('number', { message: 'Failed to add number to Signal group' }) | ||
} else { | ||
createNotification({ content: 'Number successfully added to Signal group', severity: 'success' }) | ||
callback() | ||
} | ||
}) | ||
.finally(() => { | ||
setSubmitting(false) | ||
}) | ||
}) | ||
|
||
return ( | ||
<form id="configureSignalGroupAdmin" onSubmit={onSubmit}> | ||
<Grid columnSpacing={{ xs: 1, sm: 2, md: 3 }} container rowSpacing={1}> | ||
<Grid item xs={12}> | ||
<Alert severity="warning">Only do this if extra members with write access are needed.</Alert> | ||
</Grid> | ||
<Grid item xs={12}> | ||
<FormGroup> | ||
<TextField | ||
{...register('number')} | ||
label="Phone number" | ||
placeholder="+49123456789" | ||
required | ||
helperText={errors.number ? errors.number?.message : null} | ||
error={errors.number ? true : false} | ||
InputProps={{ | ||
startAdornment: ( | ||
<InputAdornment position="start"> | ||
<FontAwesomeIcon icon={faPhone} /> | ||
</InputAdornment> | ||
), | ||
}} | ||
/> | ||
</FormGroup> | ||
</Grid> | ||
</Grid> | ||
</form> | ||
) | ||
} | ||
|
||
export default SignalGroupAdminForm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { FC, useState } from 'react' | ||
import { Ticker } from '../../api/Ticker' | ||
import Modal from '../common/Modal' | ||
import SignalGroupAdminForm from './SignalGroupAdminForm' | ||
|
||
interface Props { | ||
onClose: () => void | ||
open: boolean | ||
ticker: Ticker | ||
} | ||
|
||
const SignalGroupAdminModalForm: FC<Props> = ({ onClose, open, ticker }) => { | ||
const [submitting, setSubmitting] = useState<boolean>(false) | ||
|
||
return ( | ||
<Modal maxWidth="sm" onClose={onClose} open={open} submitForm="configureSignalGroupAdmin" title="Add Admin to group" submitting={submitting}> | ||
<SignalGroupAdminForm callback={onClose} ticker={ticker} setSubmitting={setSubmitting} /> | ||
</Modal> | ||
) | ||
} | ||
|
||
export default SignalGroupAdminModalForm |
Oops, something went wrong.