From df90467811075fd0ca11a7dd652ab6c497ca916c Mon Sep 17 00:00:00 2001 From: louis Date: Sun, 2 Feb 2025 17:05:05 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=84=20Use=20the=20submitting=20state?= =?UTF-8?q?=20when=20the=20ticker=20is=20saved?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ticker/TickerModalForm.tsx | 12 ++- .../ticker/form/TickerForm.test.tsx | 88 +++++++++++++++---- src/components/ticker/form/TickerForm.tsx | 8 +- 3 files changed, 89 insertions(+), 19 deletions(-) diff --git a/src/components/ticker/TickerModalForm.tsx b/src/components/ticker/TickerModalForm.tsx index e6a72930..3329c403 100644 --- a/src/components/ticker/TickerModalForm.tsx +++ b/src/components/ticker/TickerModalForm.tsx @@ -15,6 +15,7 @@ interface Props { } const TickerModalForm: FC = ({ onClose, open, ticker }) => { + const [submitting, setSubmitting] = useState(false) const [tabValue, setTabValue] = useState(0) const handleTabChange = (_: React.SyntheticEvent, value: number) => { @@ -22,13 +23,20 @@ const TickerModalForm: FC = ({ onClose, open, ticker }) => { } return ( - + } iconPosition="start" label="General" /> } iconPosition="start" label="Integrations" /> - + {ticker ? ( diff --git a/src/components/ticker/form/TickerForm.test.tsx b/src/components/ticker/form/TickerForm.test.tsx index 434993dd..a59b67a4 100644 --- a/src/components/ticker/form/TickerForm.test.tsx +++ b/src/components/ticker/form/TickerForm.test.tsx @@ -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: { @@ -43,7 +36,7 @@ describe('TickerForm', () => {
- +
@@ -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' }), 'author@example.org') + 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: 'author@example.org', + 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' })) @@ -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({ diff --git a/src/components/ticker/form/TickerForm.tsx b/src/components/ticker/form/TickerForm.tsx index 369dcafd..04e349b0 100644 --- a/src/components/ticker/form/TickerForm.tsx +++ b/src/components/ticker/form/TickerForm.tsx @@ -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' @@ -25,9 +25,10 @@ interface Props { id: string ticker?: Ticker callback: () => void + setSubmitting: (submitting: boolean) => void } -const TickerForm: FC = ({ callback, id, ticker }) => { +const TickerForm: FC = ({ callback, id, ticker, setSubmitting }) => { const form = useForm({ defaultValues: { title: ticker?.title, @@ -74,15 +75,18 @@ const TickerForm: FC = ({ callback, id, ticker }) => { ) const onSubmit: SubmitHandler = 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() }) }