Skip to content

Commit

Permalink
Merge pull request #712 from systemli/Use-the-submitting-state-when-t…
Browse files Browse the repository at this point in the history
…he-ticker-is-saved

💄 Use the submitting state when the ticker is saved
  • Loading branch information
0x46616c6b authored Feb 2, 2025
2 parents 59c52d0 + df90467 commit 8a8a036
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 19 deletions.
12 changes: 10 additions & 2 deletions src/components/ticker/TickerModalForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,28 @@ interface Props {
}

const TickerModalForm: FC<Props> = ({ onClose, open, ticker }) => {
const [submitting, setSubmitting] = useState<boolean>(false)
const [tabValue, setTabValue] = useState<number>(0)

const handleTabChange = (_: React.SyntheticEvent, value: number) => {
setTabValue(value)
}

return (
<Modal fullWidth onClose={onClose} open={open} submitForm={tabValue === 0 ? 'tickerForm' : undefined} title={ticker ? 'Configure Ticker' : 'Create Ticker'}>
<Modal
fullWidth
onClose={onClose}
open={open}
submitForm={tabValue === 0 ? 'tickerForm' : undefined}
title={ticker ? 'Configure Ticker' : 'Create Ticker'}
submitting={submitting}
>
<Tabs onChange={handleTabChange} value={tabValue}>
<Tab icon={<Tune />} iconPosition="start" label="General" />
<Tab disabled={!ticker} icon={<Campaign />} iconPosition="start" label="Integrations" />
</Tabs>
<TabPanel index={0} value={tabValue}>
<TickerForm callback={onClose} id="tickerForm" ticker={ticker} />
<TickerForm callback={onClose} id="tickerForm" ticker={ticker} setSubmitting={setSubmitting} />
</TabPanel>
{ticker ? (
<TabPanel index={1} value={tabValue}>
Expand Down
88 changes: 73 additions & 15 deletions src/components/ticker/form/TickerForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,15 @@ describe('TickerForm', () => {
})

const callback = vi.fn()

const ticker = () => {
return {
id: 1,
title: 'Ticker',
active: false,
information: {},
location: {},
} as Ticker
}
const setSubmitting = vi.fn()

beforeEach(() => {
fetchMock.resetMocks()
callback.mockClear()
setSubmitting.mockClear()
})

function setup(ticker: Ticker) {
function setup(ticker?: Ticker) {
const client = new QueryClient({
defaultOptions: {
queries: {
Expand All @@ -43,7 +36,7 @@ describe('TickerForm', () => {
<MemoryRouter>
<AuthProvider>
<div>
<TickerForm ticker={ticker} id="tickerForm" callback={callback} />
<TickerForm ticker={ticker} id="tickerForm" callback={callback} setSubmitting={setSubmitting} />
<input name="Submit" type="submit" value="Submit" form="tickerForm" />
</div>
</AuthProvider>
Expand All @@ -53,14 +46,78 @@ describe('TickerForm', () => {
}

it('should render the component', async () => {
setup(ticker())
setup({
id: 1,
title: 'Ticker',
active: false,
information: {},
location: {},
} as Ticker)

expect(screen.getByRole('textbox', { name: 'Title' })).toBeInTheDocument()
expect(screen.getByRole('checkbox', { name: 'Active' })).toBeInTheDocument()
})

it('should submit the form', async () => {
setup(ticker())
it('should submit for new ticker', async () => {
setup()

fetchMock.mockResponseOnce(JSON.stringify({ status: 'success' }))

await userEvent.click(screen.getByRole('checkbox', { name: 'Active' }))
await userEvent.type(screen.getByRole('textbox', { name: 'Title' }), 'New Ticker')
await userEvent.type(screen.getByRole('textbox', { name: 'Description' }), 'Description')
await userEvent.type(screen.getByRole('textbox', { name: 'Author' }), 'Author')
await userEvent.type(screen.getByRole('textbox', { name: 'Homepage' }), 'https://example.org')
await userEvent.type(screen.getByRole('textbox', { name: 'E-Mail' }), '[email protected]')
await userEvent.type(screen.getByRole('textbox', { name: 'Twitter' }), 'account')
await userEvent.type(screen.getByRole('textbox', { name: 'Facebook' }), 'account')
await userEvent.type(screen.getByRole('textbox', { name: 'Threads' }), '@account')
await userEvent.type(screen.getByRole('textbox', { name: 'Instagram' }), 'account')
await userEvent.type(screen.getByRole('textbox', { name: 'Telegram' }), 'account')
await userEvent.type(screen.getByRole('textbox', { name: 'Mastodon' }), 'https://mastodon.social/@account')
await userEvent.type(screen.getByRole('textbox', { name: 'Bluesky' }), 'https://bsky.app/profile/account.bsky.social')

await userEvent.click(screen.getByRole('button', { name: 'Submit' }))

expect(callback).toHaveBeenCalledTimes(1)
expect(setSubmitting).toHaveBeenCalledTimes(2)
expect(fetchMock).toHaveBeenCalledTimes(1)
expect(fetchMock).toHaveBeenCalledWith('http://localhost:8080/v1/admin/tickers', {
body: JSON.stringify({
title: 'New Ticker',
active: true,
description: 'Description',
information: {
author: 'Author',
email: '[email protected]',
url: 'https://example.org',
twitter: 'account',
facebook: 'account',
threads: '@account',
instagram: 'account',
telegram: 'account',
mastodon: 'https://mastodon.social/@account',
bluesky: 'https://bsky.app/profile/account.bsky.social',
},
location: { lat: 0, lon: 0 },
}),
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
method: 'post',
})
})

it('should submit for existing ticker', async () => {
setup({
id: 1,
title: 'Ticker',
active: false,
information: {},
location: {},
} as Ticker)

fetchMock.mockResponseOnce(JSON.stringify({ status: 'success' }))

Expand All @@ -82,6 +139,7 @@ describe('TickerForm', () => {
await userEvent.click(screen.getByRole('button', { name: 'Submit' }))

expect(callback).toHaveBeenCalledTimes(1)
expect(setSubmitting).toHaveBeenCalledTimes(2)
expect(fetchMock).toHaveBeenCalledTimes(1)
expect(fetchMock).toHaveBeenCalledWith('http://localhost:8080/v1/admin/tickers/1', {
body: JSON.stringify({
Expand Down
8 changes: 6 additions & 2 deletions src/components/ticker/form/TickerForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useQueryClient } from '@tanstack/react-query'
import React, { FC, useCallback, useEffect } from 'react'
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form'
import { MapContainer, Marker, TileLayer } from 'react-leaflet'
import { Ticker, TickerFormData, postTickerApi, putTickerApi } from '../../../api/Ticker'
import { postTickerApi, putTickerApi, Ticker, TickerFormData } from '../../../api/Ticker'
import useAuth from '../../../contexts/useAuth'
import LocationSearch, { Result } from '../LocationSearch'
import Active from './Active'
Expand All @@ -25,9 +25,10 @@ interface Props {
id: string
ticker?: Ticker
callback: () => void
setSubmitting: (submitting: boolean) => void
}

const TickerForm: FC<Props> = ({ callback, id, ticker }) => {
const TickerForm: FC<Props> = ({ callback, id, ticker, setSubmitting }) => {
const form = useForm<TickerFormData>({
defaultValues: {
title: ticker?.title,
Expand Down Expand Up @@ -74,15 +75,18 @@ const TickerForm: FC<Props> = ({ callback, id, ticker }) => {
)

const onSubmit: SubmitHandler<TickerFormData> = data => {
setSubmitting(true)
if (ticker) {
putTickerApi(token, data, ticker.id).finally(() => {
queryClient.invalidateQueries({ queryKey: ['tickers'] })
queryClient.invalidateQueries({ queryKey: ['ticker', ticker.id] })
setSubmitting(false)
callback()
})
} else {
postTickerApi(token, data).finally(() => {
queryClient.invalidateQueries({ queryKey: ['tickers'] })
setSubmitting(false)
callback()
})
}
Expand Down

0 comments on commit 8a8a036

Please sign in to comment.