From c0bc7a78dc6381a11ee6b85d460c054bf115643a Mon Sep 17 00:00:00 2001 From: Flaminia Cavallo Date: Tue, 13 Aug 2024 11:40:20 -0700 Subject: [PATCH] feat: add more tests and improve some of the existing ones --- .../exchange-update/exchange-form-contents.js | 5 +- .../request-update/request-form-contents.js | 5 +- src/components/edit/shared/form-subsection.js | 5 +- src/components/edit/shared/update-footer.js | 8 +- src/pages/addItem.test.js | 363 +++++++++++++++++- src/pages/editItem.test.js | 304 ++++++++++++++- 6 files changed, 674 insertions(+), 16 deletions(-) diff --git a/src/components/edit/exchange-update/exchange-form-contents.js b/src/components/edit/exchange-update/exchange-form-contents.js index 9112913..f577954 100644 --- a/src/components/edit/exchange-update/exchange-form-contents.js +++ b/src/components/edit/exchange-update/exchange-form-contents.js @@ -160,7 +160,10 @@ export const ExchangeFormContents = React.memo( {typeValue === EXCHANGE_TYPES.external && ( - + { text={i18n.t('Request setup')} className={styles.subsectionBlockEnd} > -
+
( -
+export const Subsection = ({ text, children, className = '', dataTest }) => ( +
{text}
@@ -45,5 +45,6 @@ export const Subsection = ({ text, children, className = '' }) => ( Subsection.propTypes = { children: PropTypes.node, className: PropTypes.string, + dataTest: PropTypes.string, text: PropTypes.string, } diff --git a/src/components/edit/shared/update-footer.js b/src/components/edit/shared/update-footer.js index 3c80fb2..4e17199 100644 --- a/src/components/edit/shared/update-footer.js +++ b/src/components/edit/shared/update-footer.js @@ -14,7 +14,13 @@ import { useNavigate } from 'react-router-dom' const DiscardModal = ({ open, onClose, onCancelConfirm, objectName }) => { return ( - + {i18n.t('Discard unsaved changes')} diff --git a/src/pages/addItem.test.js b/src/pages/addItem.test.js index 0f3501d..12ed758 100644 --- a/src/pages/addItem.test.js +++ b/src/pages/addItem.test.js @@ -158,6 +158,21 @@ describe('', () => { ).toBeInTheDocument() }) + it('should display a warning if the user does not have permissions to view an exchange', async () => { + const { screen } = setUp(, { + userContext: noPermissionsUserContext(), + }) + const warning = await screen.findByTestId('dhis2-uicore-noticebox') + expect(warning).toBeInTheDocument() + const backButton = screen.getByTestId('link-to-configuration-page') + expect(backButton).toBeInTheDocument() + expect( + within(backButton).getByRole('link', { + name: 'Back to configurations page', + }) + ).toBeInTheDocument() + }) + it('creates an internal exchange', async () => { const exchangeName = 'an exchange name' const requestName = 'a request name' @@ -193,13 +208,55 @@ describe('', () => { .getByText('Save exchange') .click() - waitFor(() => + await waitFor(() => expect( screen.getByTestId('saving-exchange-loader') ).toBeInTheDocument() ) }) + it('does not create an internal exchange if the name is missing', async () => { + const requestName = 'a request name' + const orgUnit = 'an org unit' + + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Add exchange') + + const typeRadio = within( + screen.getByTestId('exchange-types') + ).getAllByRole('radio') + expect(typeRadio[1].getAttribute('value')).toEqual('INTERNAL') + typeRadio[1].click() + + screen.getByText('Add request').click() + await createRequest(screen, { requestName, orgUnit }) + + const requestRow = await screen.findByTestId('dhis2-uicore-tablerow') + expect(requestRow).toHaveTextContent(requestName) + + within(screen.getByTestId('edit-item-footer')) + .getByText('Save exchange') + .click() + + const exchangeNameInputWarning = within( + screen.getByTestId('exchange-name-input') + ).getByTestId('dhis2-uiwidgets-inputfield-validation') + expect(exchangeNameInputWarning).toBeInTheDocument() + expect(exchangeNameInputWarning).toHaveTextContent( + 'Please provide a value' + ) + await waitFor(() => + expect( + screen.queryByTestId('saving-exchange-loader') + ).not.toBeInTheDocument() + ) + }) + it('creates an external exchange with auth token', async () => { const exchangeName = 'an exchange name' const exchangeURL = 'a/url' @@ -253,7 +310,7 @@ describe('', () => { .getByText('Save exchange') .click() - waitFor(() => + await waitFor(() => expect( screen.getByTestId('saving-exchange-loader') ).toBeInTheDocument() @@ -317,13 +374,192 @@ describe('', () => { .getByText('Save exchange') .click() - waitFor(() => + await waitFor(() => expect( screen.getByTestId('saving-exchange-loader') ).toBeInTheDocument() ) }) + it('does not create an external exchange if name is missing', async () => { + const exchangeURL = 'a/url' + const exchangePAT = 'anAuthToken' + const requestName = 'a request name' + const orgUnit = 'an org unit' + + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Add exchange') + + const typeRadio = within( + screen.getByTestId('exchange-types') + ).getAllByRole('radio') + expect(typeRadio[0].getAttribute('value')).toEqual('EXTERNAL') + typeRadio[0].click() + + const exchangeURLInput = within( + await screen.findByTestId('exchange-url') + ).getByLabelText('Target URL') + fireEvent.input(exchangeURLInput, { target: { value: exchangeURL } }) + + const authRadio = within( + screen.getByTestId('exchange-auth-method') + ).getAllByRole('radio') + expect(authRadio[1].getAttribute('value')).toEqual('PAT') + authRadio[1].click() + + const tokenInput = within( + screen.getByTestId('exchange-auth-pat') + ).getByLabelText('Access token') + fireEvent.input(tokenInput, { target: { value: exchangePAT } }) + + screen.getByText('Add request').click() + await createRequest(screen, { requestName, orgUnit }) + + const requestRow = await screen.findByTestId('dhis2-uicore-tablerow') + expect(requestRow).toHaveTextContent(requestName) + expect(requestRow).toHaveTextContent(orgUnit) + + within(screen.getByTestId('edit-item-footer')) + .getByText('Save exchange') + .click() + + const exchangeNameInputWarning = within( + screen.getByTestId('exchange-name-input') + ).getByTestId('dhis2-uiwidgets-inputfield-validation') + expect(exchangeNameInputWarning).toBeInTheDocument() + expect(exchangeNameInputWarning).toHaveTextContent( + 'Please provide a value' + ) + await waitFor(() => + expect( + screen.queryByTestId('saving-exchange-loader') + ).not.toBeInTheDocument() + ) + }) + + it('does not create an external exchange if auth token info are missing', async () => { + const exchangeName = 'an exchange name' + const exchangeURL = 'a/url' + const requestName = 'a request name' + const orgUnit = 'an org unit' + + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Add exchange') + + const nameInput = within( + screen.getByTestId('exchange-name-input') + ).getByLabelText('Exchange name') + fireEvent.input(nameInput, { target: { value: exchangeName } }) + + const typeRadio = within( + screen.getByTestId('exchange-types') + ).getAllByRole('radio') + expect(typeRadio[0].getAttribute('value')).toEqual('EXTERNAL') + typeRadio[0].click() + + const exchangeURLInput = within( + await screen.findByTestId('exchange-url') + ).getByLabelText('Target URL') + fireEvent.input(exchangeURLInput, { target: { value: exchangeURL } }) + + const authRadio = within( + screen.getByTestId('exchange-auth-method') + ).getAllByRole('radio') + expect(authRadio[1].getAttribute('value')).toEqual('PAT') + authRadio[1].click() + + screen.getByText('Add request').click() + await createRequest(screen, { requestName, orgUnit }) + + const requestRow = await screen.findByTestId('dhis2-uicore-tablerow') + expect(requestRow).toHaveTextContent(requestName) + expect(requestRow).toHaveTextContent(orgUnit) + + within(screen.getByTestId('edit-item-footer')) + .getByText('Save exchange') + .click() + + const exchangeAutheInputWarning = within( + screen.getByTestId('exchange-auth-pat') + ).getByTestId('dhis2-uiwidgets-inputfield-validation') + expect(exchangeAutheInputWarning).toBeInTheDocument() + expect(exchangeAutheInputWarning).toHaveTextContent( + 'Please provide a value' + ) + await waitFor(() => + expect( + screen.queryByTestId('saving-exchange-loader') + ).not.toBeInTheDocument() + ) + }) + + it('does not create an external exchange if basic auth info are missing', async () => { + const exchangeName = 'an exchange name' + const exchangeURL = 'a/url' + const requestName = 'a request name' + const orgUnit = 'an org unit' + + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Add exchange') + + const nameInput = within( + screen.getByTestId('exchange-name-input') + ).getByLabelText('Exchange name') + fireEvent.input(nameInput, { target: { value: exchangeName } }) + + const typeRadio = within( + screen.getByTestId('exchange-types') + ).getAllByRole('radio') + expect(typeRadio[0].getAttribute('value')).toEqual('EXTERNAL') + typeRadio[0].click() + + const exchangeURLInput = within( + await screen.findByTestId('exchange-url') + ).getByLabelText('Target URL') + fireEvent.input(exchangeURLInput, { target: { value: exchangeURL } }) + + const authRadio = within( + screen.getByTestId('exchange-auth-method') + ).getAllByRole('radio') + expect(authRadio[0].getAttribute('value')).toEqual('BASIC') + authRadio[0].click() + + screen.getByText('Add request').click() + await createRequest(screen, { requestName, orgUnit }) + + const requestRow = await screen.findByTestId('dhis2-uicore-tablerow') + expect(requestRow).toHaveTextContent(requestName) + + within(screen.getByTestId('edit-item-footer')) + .getByText('Save exchange') + .click() + + const exchangeAuthInputWarnings = within( + screen.getByTestId('exchange-auth-basic') + ).getAllByTestId('dhis2-uiwidgets-inputfield-validation') + expect(exchangeAuthInputWarnings).toHaveLength(2) + await waitFor(() => + expect( + screen.queryByTestId('saving-exchange-loader') + ).not.toBeInTheDocument() + ) + }) + it('creates an internal exchange with codes as ID schemes', async () => { const exchangeName = 'an exchange name' const requestName = 'a request name' @@ -380,7 +616,7 @@ describe('', () => { .getByText('Save exchange') .click() - waitFor(() => + await waitFor(() => expect( screen.getByTestId('saving-exchange-loader') ).toBeInTheDocument() @@ -500,10 +736,127 @@ describe('', () => { .getByText('Save exchange') .click() - waitFor(() => + await waitFor(() => expect( screen.getByTestId('saving-exchange-loader') ).toBeInTheDocument() ) }) + + it('warns about unsaved changes if user clicks cancel after making changes in the form', async () => { + const exchangeName = 'an exchange name' + + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Add exchange') + + const exchangeNameInput = within( + screen.getByTestId('exchange-name-input') + ).getByLabelText('Exchange name') + fireEvent.input(exchangeNameInput, { target: { value: exchangeName } }) + + within(screen.getByTestId('edit-item-footer')) + .getByText('Cancel') + .click() + + const warningModal = await screen.findByTestId('exchange-discard-modal') + expect(warningModal).toBeVisible() + expect(warningModal).toHaveTextContent('Discard unsaved changes') + }) + + it('does not warn about unsaved changes if user clicks cancel after making no changes in the form ', async () => { + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Add exchange') + + within(screen.getByTestId('edit-item-footer')) + .getByText('Cancel') + .click() + + const warningModal = await screen.findByTestId('exchange-discard-modal') + expect(warningModal).not.toBeVisible() + }) + + it('does not create a request if the request name is missing', async () => { + const orgUnit = 'an org unit' + + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Add exchange') + + screen.getByText('Add request').click() + + fireEvent.input(screen.getByTestId('fake-data-selector'), { + target: { value: 'a data element' }, + }) + fireEvent.input(screen.getByTestId('fake-period-selector'), { + target: { value: 'a period' }, + }) + fireEvent.input(screen.getByTestId('fake-orgunit-selector'), { + target: { value: orgUnit }, + }) + const footer = screen.getByTestId('edit-request-footer') + within(footer).getByText('Save request').click() + + const requestNameInputWarning = within( + screen.getByTestId('request-name') + ).getByTestId('dhis2-uiwidgets-inputfield-validation') + expect(requestNameInputWarning).toBeInTheDocument() + expect(requestNameInputWarning).toHaveTextContent( + 'Please provide a value' + ) + }) + + it('warns about unsaved changes if user clicks cancel after making changes in the request form', async () => { + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Add exchange') + + screen.getByText('Add request').click() + const requestNameInput = await screen.findByLabelText('Request name') + fireEvent.input(requestNameInput, { target: { value: 'a request' } }) + + const footer = screen.getByTestId('edit-request-footer') + within(footer).getByText('Cancel').click() + + const warningModal = await screen.findByTestId('request-discard-modal') + expect(warningModal).toBeVisible() + expect(warningModal).toHaveTextContent('Discard unsaved changes') + }) + + it('does not warn about unsaved changes if user clicks cancel after making no changes in the request form', async () => { + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Add exchange') + + screen.getByText('Add request').click() + + const footer = screen.getByTestId('edit-request-footer') + within(footer).getByText('Cancel').click() + + await waitFor(() => { + const warningModal = screen.queryByTestId('request-discard-modal') + expect(warningModal).not.toBeInTheDocument() + }) + }) }) diff --git a/src/pages/editItem.test.js b/src/pages/editItem.test.js index af75054..e2c7518 100644 --- a/src/pages/editItem.test.js +++ b/src/pages/editItem.test.js @@ -72,17 +72,27 @@ const setUp = ( { userContext = testUserContext(), attributes = [testAttribute(), testAttribute()], + exchangeId = null, dataExchange = testDataExchange(), } = {} ) => { + const exchangeIdOrDataExchangeId = exchangeId || dataExchange.id const customerProviderData = { attributes: { attributes }, aggregateDataExchanges: (type) => { if (type === 'read') { - return dataExchange + return dataExchange.id === exchangeIdOrDataExchangeId + ? dataExchange + : null + } + if (type === 'create') { + return {} } return undefined }, + [`aggregateDataExchanges/${exchangeIdOrDataExchangeId}`]: () => { + return {} + }, analytics: { headers: [], metaData: { items: {}, dimensions: {} } }, organisationUnits: { organisationUnits: [] }, visualizations: { visualizations: [] }, @@ -99,7 +109,9 @@ const setUp = ( const screen = render( - + {}, @@ -154,6 +166,10 @@ describe('', () => { }) const warning = await screen.findByTestId('dhis2-uicore-noticebox') expect(warning).toBeInTheDocument() + expect(warning).toHaveTextContent( + 'The requested exchange does not exist, or you do not have the relevant authorities to edit it.' + ) + const backButton = screen.getByTestId('link-to-configuration-page') expect(backButton).toBeInTheDocument() expect( @@ -201,7 +217,10 @@ describe('', () => { it('edits an exchange info', async () => { const request = testRequest() - const dataExchange = testDataExchange({ requests: [request] }) + const dataExchange = testDataExchange({ + requests: [request], + targetType: 'INTERNAL', + }) const newExchangeName = 'new name' const { screen } = setUp(, { @@ -217,6 +236,16 @@ describe('', () => { screen.getByTestId('exchange-name-input') ).getByLabelText('Exchange name') fireEvent.input(nameInput, { target: { value: newExchangeName } }) + + within(screen.getByTestId('edit-item-footer')) + .getByText('Save exchange') + .click() + + await waitFor(() => + expect( + screen.getByTestId('saving-exchange-loader') + ).toBeInTheDocument() + ) }) it('deletes the exchange request', async () => { @@ -241,10 +270,13 @@ describe('', () => { }) }) - it('add an exchange request', async () => { + it('adds an exchange request', async () => { const existingRequest = testRequest() const newRequestName = 'a new request' - const dataExchange = testDataExchange({ requests: [existingRequest] }) + const dataExchange = testDataExchange({ + requests: [existingRequest], + targetType: 'INTERNAL', + }) const { screen } = setUp(, { userContext: testUserContext({ canAddExchange: true }), @@ -262,5 +294,265 @@ describe('', () => { expect(requestRow).toHaveLength(2) expect(requestRow[0]).toHaveTextContent(existingRequest.name) expect(requestRow[1]).toHaveTextContent(newRequestName) + + within(screen.getByTestId('edit-item-footer')) + .getByText('Save exchange') + .click() + + await waitFor(() => + expect( + screen.getByTestId('saving-exchange-loader') + ).toBeInTheDocument() + ) + }) + + it('can not edit an external exchange target setup if not explicitly specified', async () => { + const request = testRequest() + const dataExchange = testDataExchange({ + requests: [request], + targetType: 'EXTERNAL', + }) + + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + dataExchange, + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Edit exchange') + + const exchangeURLInput = within( + await screen.findByTestId('exchange-url') + ).getByLabelText('Target URL') + expect(exchangeURLInput).toBeDisabled() + }) + + it('can edit an external exchange target setup if explicitly specified', async () => { + const request = testRequest() + const dataExchange = testDataExchange({ + requests: [request], + targetType: 'EXTERNAL', + externalURL: 'anExchangeUrl.com', + }) + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + dataExchange, + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Edit exchange') + + within(screen.getByTestId('target-setup')) + .queryByRole('button', { + name: 'Edit target setup', + }) + .click() + + const exchangeURLInput = within( + await screen.findByTestId('exchange-url') + ).getByLabelText('Target URL') + expect(exchangeURLInput).not.toBeDisabled() + + fireEvent.input(exchangeURLInput, { + target: { value: 'newExchangeUrl.com' }, + }) + + const authRadio = within( + screen.getByTestId('exchange-auth-method') + ).getAllByRole('radio') + expect(authRadio[1].getAttribute('value')).toEqual('PAT') + authRadio[1].click() + + const tokenInput = within( + screen.getByTestId('exchange-auth-pat') + ).getByLabelText('Access token') + fireEvent.input(tokenInput, { target: { value: 'exchangePAT' } }) + + within(screen.getByTestId('edit-item-footer')) + .getByText('Save exchange') + .click() + + await waitFor(() => + expect( + screen.getByTestId('saving-exchange-loader') + ).toBeInTheDocument() + ) + }) + + it('can not edit an external exchange advanced options if not explicitly specified', async () => { + const request = testRequest() + const dataExchange = testDataExchange({ + requests: [request], + targetType: 'EXTERNAL', + }) + + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + dataExchange, + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Edit exchange') + + screen.getByTestId('advanced-options').click() + + const generalIdSchemeRadio = within( + screen.getByTestId('general-id-scheme-selector') + ).getAllByRole('radio') + generalIdSchemeRadio.map((r) => expect(r).toBeDisabled()) + + const elementIdSchemeRadio = within( + screen.getByTestId('element-id-scheme-selector') + ).getAllByRole('radio') + elementIdSchemeRadio.map((r) => expect(r).toBeDisabled()) + + const orgUnitIdSchemeRadio = within( + screen.getByTestId('org-unit-id-scheme-selector') + ).getAllByRole('radio') + orgUnitIdSchemeRadio.map((r) => expect(r).toBeDisabled()) + + const categoryOptionComboSchemeRadio = within( + screen.getByTestId('category-option-combo-scheme-selector') + ).getAllByRole('radio') + categoryOptionComboSchemeRadio.map((r) => expect(r).toBeDisabled()) + }) + + it('can not edit an external exchange target advanced options if explicitly specified but auth info is not re-entered ', async () => { + const request = testRequest() + const dataExchange = testDataExchange({ + requests: [request], + targetType: 'EXTERNAL', + externalURL: 'a/url', + }) + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + dataExchange, + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Edit exchange') + + screen.getByTestId('advanced-options').click() + + const editButton = await screen.findByRole('button', { + name: 'Edit advanced options', + }) + + editButton.click() + + const generalIdSchemeRadio = within( + screen.getByTestId('general-id-scheme-selector') + ).getAllByRole('radio') + generalIdSchemeRadio.map((r) => expect(r).not.toBeDisabled()) + generalIdSchemeRadio[1].click() + + const elementIdSchemeRadio = within( + screen.getByTestId('element-id-scheme-selector') + ).getAllByRole('radio') + elementIdSchemeRadio.map((r) => expect(r).not.toBeDisabled()) + elementIdSchemeRadio[1].click() + + const orgUnitIdSchemeRadio = within( + screen.getByTestId('org-unit-id-scheme-selector') + ).getAllByRole('radio') + orgUnitIdSchemeRadio.map((r) => expect(r).not.toBeDisabled()) + orgUnitIdSchemeRadio[1].click() + + const categoryOptionComboSchemeRadio = within( + screen.getByTestId('category-option-combo-scheme-selector') + ).getAllByRole('radio') + categoryOptionComboSchemeRadio.map((r) => expect(r).not.toBeDisabled()) + categoryOptionComboSchemeRadio[1].click() + + within(screen.getByTestId('edit-item-footer')) + .getByText('Save exchange') + .click() + + const exchangeAutheInputWarning = within( + screen.getByTestId('exchange-auth-pat') + ).getByTestId('dhis2-uiwidgets-inputfield-validation') + expect(exchangeAutheInputWarning).toBeInTheDocument() + expect(exchangeAutheInputWarning).toHaveTextContent( + 'Please provide a value' + ) + await waitFor(() => + expect( + screen.queryByTestId('saving-exchange-loader') + ).not.toBeInTheDocument() + ) + }) + + it('can edit an external exchange target advanced options if explicitly specified and auth info is re-entered', async () => { + const request = testRequest() + const dataExchange = testDataExchange({ + requests: [request], + targetType: 'EXTERNAL', + externalURL: 'a/url', + }) + const { screen } = setUp(, { + userContext: testUserContext({ canAddExchange: true }), + dataExchange, + }) + + expect( + await screen.findByTestId('add-exchange-title') + ).toHaveTextContent('Edit exchange') + + screen.getByTestId('advanced-options').click() + + const editButton = await screen.findByRole('button', { + name: 'Edit advanced options', + }) + + editButton.click() + + const generalIdSchemeRadio = within( + screen.getByTestId('general-id-scheme-selector') + ).getAllByRole('radio') + generalIdSchemeRadio.map((r) => expect(r).not.toBeDisabled()) + generalIdSchemeRadio[1].click() + + const elementIdSchemeRadio = within( + screen.getByTestId('element-id-scheme-selector') + ).getAllByRole('radio') + elementIdSchemeRadio.map((r) => expect(r).not.toBeDisabled()) + elementIdSchemeRadio[1].click() + + const orgUnitIdSchemeRadio = within( + screen.getByTestId('org-unit-id-scheme-selector') + ).getAllByRole('radio') + orgUnitIdSchemeRadio.map((r) => expect(r).not.toBeDisabled()) + orgUnitIdSchemeRadio[1].click() + + const categoryOptionComboSchemeRadio = within( + screen.getByTestId('category-option-combo-scheme-selector') + ).getAllByRole('radio') + categoryOptionComboSchemeRadio.map((r) => expect(r).not.toBeDisabled()) + categoryOptionComboSchemeRadio[1].click() + + const authRadio = within( + screen.getByTestId('exchange-auth-method') + ).getAllByRole('radio') + expect(authRadio[1].getAttribute('value')).toEqual('PAT') + authRadio[1].click() + + const tokenInput = within( + screen.getByTestId('exchange-auth-pat') + ).getByLabelText('Access token') + fireEvent.input(tokenInput, { target: { value: 'exchangePAT' } }) + + within(screen.getByTestId('edit-item-footer')) + .getByText('Save exchange') + .click() + + await waitFor(() => + expect( + screen.getByTestId('saving-exchange-loader') + ).toBeInTheDocument() + ) }) })