diff --git a/app/src/components/Download.cy.js b/app/src/components/Download.cy.js index cf61eedc..4f33edf8 100644 --- a/app/src/components/Download.cy.js +++ b/app/src/components/Download.cy.js @@ -127,6 +127,15 @@ describe('', () => { shouldBeInvalid('#url_input'); }); + it('can be submitted with a frequency of Once', () => { + cy.get('#url_input').type('https://example.com/playlist').wait(500); + cy.get('#frequency_select').click(); + cy.contains('[role="option"]:visible', 'Once').should('be.visible').click({force: true}); + cy.get('#frequency_select').should('have.value', 'Once'); + + cy.get('#download_form_download_button').should('not.be.disabled'); + }); + it('can choose different options', () => { /* * `#download_frequency_selector` and `.item` named the old dropdown and its menu rows. diff --git a/app/src/hooks/useForm.js b/app/src/hooks/useForm.js index 0c03ec7c..8959a43d 100644 --- a/app/src/hooks/useForm.js +++ b/app/src/hooks/useForm.js @@ -67,7 +67,11 @@ export function useForm({ setReady(false); return } - const missingValues = Object.keys(memoizedRequires).filter(i => !_.get(formData, i)); + // 0 is a real value (a download frequency of "Once"), only empty values are missing. + const missingValues = Object.keys(memoizedRequires).filter(i => { + const value = _.get(formData, i); + return value === null || value === undefined || value === '' || value === false || Number.isNaN(value); + }); if (missingValues.length > 0) { console.debug(`Form invalid because it is missing required value: ${missingValues[0]}`); setReady(false); diff --git a/app/src/hooks/useForm.test.js b/app/src/hooks/useForm.test.js index 443f0411..9d37ea62 100644 --- a/app/src/hooks/useForm.test.js +++ b/app/src/hooks/useForm.test.js @@ -727,6 +727,29 @@ describe('useForm', () => { }); }); + it('zero satisfies a required field', async () => { + // A download frequency of 0 means "Once". + const {result} = renderHook(() => useForm({ + defaultFormData: {frequency: null}, + submitter: jest.fn(), + })); + + act(() => { + result.current.getCustomProps({name: 'frequency', required: true}); + }); + await waitFor(() => { + expect(result.current.ready).toBe(false); + }); + + act(() => { + result.current.setValue('frequency', 0); + }); + await waitFor(() => { + expect(result.current.formData.frequency).toBe(0); + expect(result.current.ready).toBe(true); + }); + }); + it('addRequires marks field as required', async () => { const {result} = renderHook(() => useForm({ defaultFormData: {field: ''},