@testing-library/react#getByText JavaScript Examples

The following examples show how to use @testing-library/react#getByText. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.jsdom.test.jsx    From apps-todo-list with MIT License 6 votes vote down vote up
function getItems() {
    return screen.queryAllByRole('checkbox').map(checkbox => {
        const container = checkbox.parentNode;
        const deleteButton = getByRole(container, 'button');
        const link = getByText(container, container.textContent.trim());

        return {container, checkbox, deleteButton, link};
    });
}
Example #2
Source File: TextIcon.spec.js    From dev-jot with MIT License 6 votes vote down vote up
describe('TextIcon', () => {
  const props = {
    icon: 'some icon',
    text: 'some text',
    alt: 'some description',
  };

  it('should render TextIcon component properly', () => {
    const { getByText } = render(<TextIcon {...props} />);
    expect(getByText('some text')).toBeInTheDocument();
  });
});
Example #3
Source File: TutorialPage.test.js    From trashpanda-fe with MIT License 6 votes vote down vote up
describe("TutorialPage", () => {
  afterEach(cleanup);

  it("renders TutorialPage", async () => {
    const page = render(
      <MockedProvider addTypename={false}>
        <TutorialPage theme={lightTheme} />
      </MockedProvider>
    );
    await waitForElement(() =>
      page.getByText(/Here to help you create better recycling habits./i)
    );
    await waitForElement(() => page.getByText(/Next/i));
  });

  it("fires next button", async () => {
    const page = render(
      <MockedProvider addTypename={false}>
        <TutorialPage theme={lightTheme} />
      </MockedProvider>
    );

    fireEvent.click(page.getByText(/Next/i));
    page.debug();

    expect(
      page.getByText(
        /Let us use your location to help you properly dispose of the item./i
      )
    ).toBeTruthy();
  });
});
Example #4
Source File: LocationsPage.test.js    From trashpanda-fe with MIT License 6 votes vote down vote up
describe("LocationsPage", () => {
  afterEach(cleanup);

  it("renders LocationsPage and blurb, and queries are used without error", async () => {
    const page = render(
      <MockedProvider
        mocks={(mocksQueryLocations, mocksQueryPostal, mocksQueryZip)}
        addTypename={false}
      >
        <LocationsPage location={mockUserLocation} />
      </MockedProvider>
    );
    page.debug();
    await waitForElement(() => page.getByText(/Where can I bring this?/i));
  });
});
Example #5
Source File: HomePage.test.js    From trashpanda-fe with MIT License 6 votes vote down vote up
describe("HomePage", () => {
  afterEach(cleanup);

  it("renders HomePage and GridCards based on description of mock Category List", async () => {
    const page = render(
      <MockedProvider mocks={mocksQuery} addTypename={false}>
        <HomePage />
      </MockedProvider>
    );
    await waitForElement(() => page.getByText(/first family/i));
    await waitForElement(() => page.getByText(/second family/i));
  });

  it("renders HomePage and input field with placeholder text 'enter search term'", async () => {
    const page = render(
      <MockedProvider mocks={mocksQuery} addTypename={false}>
        <HomePage />
      </MockedProvider>
    );
    await waitForElement(() => page.getByPlaceholderText(/enter search term/i));
  });

  //NO TEXT CHANGES ON FIRED EVENTS
});
Example #6
Source File: CategoryPage.test.js    From trashpanda-fe with MIT License 6 votes vote down vote up
describe("CategoryPage", () => {
  const cache = new InMemoryCache();

  afterEach(cleanup);

  it("renders CategoryPage and title based on description of mock Category 1(using params argument)", async () => {
    const page = render(
      <MockedProvider cache={cache} addTypename={false}>
        <CategoryPage categories={mockCategoryList} materials={mockMaterials} />
      </MockedProvider>
    );
    page.debug();
    await waitForElement(() => page.getByText(/first family/i));
  });

  it("renders CategoryPage and, after iterating over mocked catergory 1 material_ids, it renders grid cards with names of mocked material instances 1, 2 and 4", async () => {
    const page = render(
      <MockedProvider cache={cache} addTypename={false}>
        <CategoryPage categories={mockCategoryList} materials={mockMaterials} />
      </MockedProvider>
    );
    page.debug();
    await waitForElement(() => page.getByText(/first material/i));
    await waitForElement(() => page.getByText(/second material/i));
    await waitForElement(() => page.getByText(/fourth material/i));
  });
});
Example #7
Source File: Landing-Page.test.js    From Encon-fe with MIT License 6 votes vote down vote up
test('should render the landing page correctly ', () => {
  const { getByText } = render(
    <Router>
      <LandingPage />
    </Router>
  );
  const headerText = getByText('Welcome to EnCon!');
  expect(headerText).toBeTruthy();
});
Example #8
Source File: Dashboard.test.js    From Encon-fe with MIT License 6 votes vote down vote up
test('should render the appliance list after button is clicked', () => {
  const { getByText } = render(
    <Router>
      <Dashboard />
    </Router>
  );
  act(() => {
    const applianceButton = getByText('Appliance List');
    fireEvent.click(applianceButton);
  });
  const inputEnergy = getByText('Input Daily Energy');
  expect(inputEnergy).toBeInTheDocument();
});
Example #9
Source File: Dashboard.test.js    From Encon-fe with MIT License 6 votes vote down vote up
test('should render dashboard and see if the appliance list is on there', () => {
  const { getByText } = render(
    <Router>
      <Dashboard />
    </Router>
  );
  const dashboardText = getByText(/Appliance List/i);
  expect(dashboardText).toBeInTheDocument();
});
Example #10
Source File: index.jsdom.test.jsx    From apps-todo-list with MIT License 6 votes vote down vote up
async function openAsync(table, view, field) {
    act(() => {
        const input = screen.getByLabelText('Table');
        const option = screen.getByText(table);

        userEvent.selectOptions(input, [option]);
    });

    act(() => {
        const input = screen.getByLabelText('View');
        const option = screen.getByText(view);

        userEvent.selectOptions(input, [option]);
    });

    act(() => {
        const input = screen.getByLabelText('Field');
        const option = screen.getByText(field);

        userEvent.selectOptions(input, [option]);
    });

    return waitFor(() => screen.getByRole('button', {name: 'Add'}));
}
Example #11
Source File: MaterialPage.test.js    From trashpanda-fe with MIT License 5 votes vote down vote up
describe("MaterialPage", () => {
  afterEach(cleanup);

  it("renders MaterialPage without error and checks for the existence of an element with the text 'Locate Centers'", async () => {
    const page = render(
      <MockedProvider>
        <MaterialPage />
      </MockedProvider>
    );
    //some useful methods commented out below
    // await Promise.resolve();
    // page.debug();
    expect(page).toEqual(
      expect.objectContaining({
        baseElement: expect.anything()
      })
    );

    await waitForElement(() => page.getByText(/Locate Centers/i));
  });

  it("renders MaterialPage and checks that Badge component is being called/imported", async () => {
    const page = render(
      <MockedProvider mocks={mocksQuery} addTypename={false}>
        <MaterialPage />
      </MockedProvider>
    );

    await waitForElement(() => page.getByText(/some fake image/i));
  });

  it("renders MaterialPage and calls an Actual query that checks mock response against mock materials, then checks the page for an element that contains the text that would be rendered if that query was satisfied", async () => {
    const page = render(
      <MockedProvider mocks={mocksQuery} addTypename={false}>
        <MaterialPage />
      </MockedProvider>
    );

    await waitForElement(() => page.getByText(/The first mocked material/i));
  });
});
Example #12
Source File: ChooseJobProfilePage.test.js    From ui-data-export with Apache License 2.0 4 votes vote down vote up
describe('ChooseJobProfile', () => {
  describe('rendering ChooseJobProfile', () => {
    const exportProfileSpy = jest.fn(Promise.resolve.bind(Promise));
    const pushHistorySpy = jest.fn();
    const mutator = buildMutator({ export: { POST: exportProfileSpy } });
    const location = { state: { fileDefinitionId: 'fileDefinitionId' } };
    let renderResult;

    beforeEach(() => {
      renderResult = renderWithIntl(
        <Router>
          <ChooseJobProfile
            resources={resources}
            mutator={mutator}
            history={{ push: pushHistorySpy }}
            location={location}
          />
        </Router>,
        translationsProperties
      );
    });

    afterEach(() => {
      jest.clearAllMocks();
    });

    it('should be visible', () => {
      const { container } = renderResult;

      expect(container.querySelector('#pane-results')).toBeVisible();
    });

    it('should display correct title and subtitle', () => {
      const { container } = renderResult;
      const paneHeader = container.querySelector('[data-test-pane-header]');

      expect(getByText(paneHeader, 'Select job profile to run the export')).toBeVisible();
      expect(getByText(paneHeader, '2 job profiles')).toBeVisible();
    });

    it('should place headers in correct order', () => {
      const { container } = renderResult;
      const headers = container.querySelectorAll('#search-results-list .mclHeader');

      expect(getByText(headers[0], 'Name')).toBeVisible();
      expect(getByText(headers[1], 'Description')).toBeVisible();
      expect(getByText(headers[2], 'Updated')).toBeVisible();
      expect(getByText(headers[3], 'Updated by')).toBeVisible();
    });

    it('should not display the confirmation modal', () => {
      const { container } = renderResult;
      const modal = container.querySelector('#choose-job-profile-confirmation-modal');

      expect(modal).not.toBeInTheDocument();
    });

    it('should display correct data for the first row', () => {
      const { container } = renderResult;
      const row = container.querySelector('.mclRow');
      const cells = row.querySelectorAll('.mclCell');

      expect(getByText(cells[0], 'A Lorem ipsum 1')).toBeVisible();
      expect(getByText(cells[1], 'Description 1')).toBeVisible();
      expect(getByText(cells[2], '12/4/2018')).toBeVisible();
      expect(getByText(cells[3], 'Donald S')).toBeVisible();
    });

    describe('clicking on row', () => {
      beforeEach(() => {
        const { container } = renderResult;
        const row = container.querySelector('.mclRow');

        userEvent.click(row);
      });

      it('should display modal with proper header', () => {
        expect(screen.getByText('Are you sure you want to run this job?')).toBeInTheDocument();
      });

      it('should display modal profile name in the body', () => {
        expect(screen.getByTestId('choose-job-select')).toBeVisible();
      });

      it('should display modal with proper wording for buttons', () => {
        const modal = document.querySelector('#choose-job-profile-confirmation-modal');

        expect(getByRole(modal, 'button', { name: 'Run' })).toBeVisible();
        expect(getByRole(modal, 'button', { name: 'Cancel' })).toBeVisible();
      });

      it('clicking on cancel button should close the modal', () => {
        const modal = document.querySelector('#choose-job-profile-confirmation-modal');

        userEvent.click(getByRole(modal, 'button', { name: 'Cancel' }));

        return waitForElementToBeRemoved(() => document.querySelector('#choose-job-profile-confirmation-modal'));
      });

      describe('clicking on confirm button - success case', () => {
        beforeEach(async () => {
          const modal = document.querySelector('#choose-job-profile-confirmation-modal');

          await userEvent.selectOptions(getByTestId(modal, 'choose-job-select'), 'Instances');

          userEvent.click(getByRole(modal, 'button', { name: 'Run' }));
        });

        it('should navigate to the landing page', () => {
          expect(pushHistorySpy).toHaveBeenCalledWith('/data-export');
        });
      });

      describe('clicking on confirm button - error case', () => {
        beforeEach(async () => {
          const modal = document.querySelector('#choose-job-profile-confirmation-modal');

          exportProfileSpy.mockImplementationOnce(Promise.reject.bind(Promise));

          await userEvent.selectOptions(getByTestId(modal, 'choose-job-select'), 'Instances');

          userEvent.click(getByRole(modal, 'button', { name: 'Run' }));
          await waitForElementToBeRemoved(() => document.querySelector('#choose-job-profile-confirmation-modal'));
        });

        it('should not navigate to the landing page', () => {
          expect(pushHistorySpy).not.toHaveBeenCalled();
        });
      });
    });
  });
});
Example #13
Source File: CreateMappingProfileFormRoute.test.js    From ui-data-export with Apache License 2.0 4 votes vote down vote up
describe('CreateMappingProfileFormRoute', () => {
  describe('creating new mapping profile', () => {
    const onSubmitNavigateMock = jest.fn();
    const onSubmitMock = jest.fn();
    const sendCalloutMock = jest.fn();

    beforeEach(() => {
      renderWithIntl(
        <CreateMappingProfileFormRouteContainer
          allTransformations={allMappingProfilesTransformations}
          sendCallout={sendCalloutMock}
          onSubmitNavigate={onSubmitNavigateMock}
          onSubmit={onSubmitMock}
        />,
        translationsProperties
      );
    });

    afterEach(() => {
      jest.clearAllMocks();
    });

    it('should initiate creating of mapping profile with correct values', async () => {
      const name = 'New mapping profile';
      const submitFormButton = screen.getByRole('button', { name: 'Save & close' });

      userEvent.type(screen.getByLabelText('Name*'), name);
      userEvent.click(recordTypesHoldings());
      userEvent.click(screen.getByRole('button', { name: 'Add transformations' }));

      const modal = screen.getByRole('document');
      const saveTransrormationsButton = within(modal).getByRole('button', { name: 'Save & close' });
      const tableRow = screen.getByRole('row', { name: 'Holdings - Call number - Call number' });
      const checkbox = within(tableRow).getByRole('checkbox');
      const textFields = within(tableRow).getAllByRole('textbox');

      userEvent.click(checkbox);
      userEvent.type(textFields[0], '500');
      userEvent.type(textFields[3], '$a');
      userEvent.click(saveTransrormationsButton);

      userEvent.click(submitFormButton);

      await waitFor(() => {
        expect(sendCalloutMock.mock.calls[0][0]).not.toHaveProperty('type');
        expect(sendCalloutMock.mock.calls[0][0].message.props.id).toBe('ui-data-export.mappingProfiles.create.successCallout');
        expect(onSubmitNavigateMock).toHaveBeenCalled();
      });
    });

    it('should display validation error when name field is empty', () => {
      userEvent.click(recordTypesHoldings());
      userEvent.click(saveAndCloseBtn());

      expect(getByText(document.querySelector('[data-test-mapping-profile-form-name]'), 'Please enter a value')).toBeVisible();
      expect(screen.getByLabelText('Name*')).not.toBeValid();
      expect(onSubmitMock).not.toBeCalled();
    });

    it('should initiate displaying of error callout', async () => {
      onSubmitMock.mockImplementationOnce(() => Promise.reject());

      const submitFormButton = screen.getByRole('button', { name: 'Save & close' });

      userEvent.type(screen.getByLabelText('Name*'), 'Name');
      userEvent.click(screen.getByRole('checkbox', { name: 'Holdings' }));
      userEvent.click(screen.getByRole('button', { name: 'Add transformations' }));

      const modal = screen.getByRole('document');
      const saveTransrormationsButton = within(modal).getByRole('button', { name: 'Save & close' });
      const tableRow = screen.getByRole('row', { name: 'Holdings - Call number - Call number' });
      const checkbox = within(tableRow).getByRole('checkbox');
      const textFields = within(tableRow).getAllByRole('textbox');

      userEvent.click(checkbox);
      userEvent.type(textFields[0], '500');
      userEvent.type(textFields[3], '$a');
      userEvent.click(saveTransrormationsButton);

      userEvent.click(submitFormButton);

      await waitFor(() => {
        expect(sendCalloutMock).toBeCalledWith(
          expect.objectContaining({ type: 'error' })
        );
        expect(sendCalloutMock.mock.calls[0][0].message.props.id).toBe('ui-data-export.mappingProfiles.create.errorCallout');
      });
    });
  });
});
Example #14
Source File: DuplicateMappingProfileRoute.test.js    From ui-data-export with Apache License 2.0 4 votes vote down vote up
describe('DuplicateMappingProfileRoute', () => {
  describe('rendering duplicate mapping profile page with profile data: success scenario', () => {
    const handleSubmitMock = jest.fn();
    const handleCancelMock = jest.fn();
    const handleSubmitNavigateMock = jest.fn();
    const sendCalloutMock = jest.fn();

    const renderDuplicateMappingProfileRoute = () => renderWithIntl(
      <DuplicateMappingProfileRouteContainer allTransformations={allMappingProfilesTransformations} />,
      translationsProperties
    );

    const renderDuplicateMappingProfileRouteWithMocks = () => renderWithIntl(
      <DuplicateMappingProfileRouteContainer
        allTransformations={allMappingProfilesTransformations}
        sendCallout={sendCalloutMock}
        onSubmit={handleSubmitMock}
        onSubmitNavigate={handleSubmitNavigateMock}
        onCancel={handleCancelMock}
      />,
      translationsProperties
    );

    beforeEach(() => {
      jest.clearAllMocks();
    });

    it('should display the form', () => {
      const { container } = renderDuplicateMappingProfileRoute();
      const form = container.querySelector('[data-test-full-screen-form]');

      expect(form).toBeVisible();
    });

    it('should display correct pane title', () => {
      renderDuplicateMappingProfileRoute();

      expect(getByText(paneHeader('New field mapping profile'), translations['mappingProfiles.newProfile'])).toBeVisible();
    });

    it('should have correct name field value', () => {
      renderDuplicateMappingProfileRoute();
      expect(nameField()).toHaveValue(`Copy of ${mappingProfile.name}`);
    });

    it('should display add transformations button with proper wording', () => {
      renderDuplicateMappingProfileRoute();

      expect(getByText(transformationsBtn('Add transformations'), translations['mappingProfiles.transformations.addTransformations'])).toBeVisible();
    });

    it('should have correct description field value', () => {
      renderDuplicateMappingProfileRoute();
      expect(descriptionField()).toHaveValue(mappingProfile.description);
    });

    it('should have enabled save button if there are no changes', () => {
      renderDuplicateMappingProfileRoute();
      expect(saveAndCloseBtn()).toBeEnabled();
    });

    it('should have correct folio record types field checked', () => {
      renderDuplicateMappingProfileRoute();

      expect(recordTypeInstance()).toBeChecked();
      expect(recordTypesSRS()).not.toBeChecked();
      expect(recordTypesHoldings()).not.toBeChecked();
      expect(recordTypesItem()).not.toBeChecked();
    });

    it('should display in form proper values', async () => {
      renderDuplicateMappingProfileRoute();

      userEvent.clear(nameField());
      userEvent.type(nameField(), 'Change name');
      userEvent.clear(descriptionField());
      userEvent.type(descriptionField(), 'Updated value');
      userEvent.type(recordTypesHoldings(), 'instance');
      userEvent.click(saveAndCloseBtn());

      expect(nameField()).toHaveValue('Change name');
      expect(descriptionField()).toHaveValue('Updated value');
      expect(recordTypesHoldings()).toBeChecked();
    });

    describe('clicking on cancel button', () => {
      it('should call cancel callback', () => {
        renderDuplicateMappingProfileRouteWithMocks();

        userEvent.click(screen.getByText(/cancel/i));

        expect(handleCancelMock).toHaveBeenCalled();
      });
    });

    describe('opening transformations modal', () => {
      it('should display correct transformations table with filled values', () => {
        renderDuplicateMappingProfileRoute();
        userEvent.click(transformationsBtn('Add transformations'));

        expect(columnHeaderFieldName()[0]).toBeVisible();
        expect(columnHeaderTransformation()[0]).toBeVisible();
        expect(transformationListCells()).toBeVisible();
      });

      it('should fill transformation field group on transformation modal correctly', () => {
        renderDuplicateMappingProfileRoute();

        userEvent.click(transformationsBtn('Add transformations'));

        const transformationFields = getTransformationFieldGroups();

        expect(transformationFields[2].marcField.input.value).toBe('900');
        expect(transformationFields[2].indicator1.input.value).toBe('');
        expect(transformationFields[2].indicator2.input.value).toBe('1');
        expect(transformationFields[2].subfield.input.value).toBe('$12');
      });

      it('should not show validation error when clearing transformation with empty indicator field', () => {
        const { container } = renderDuplicateMappingProfileRoute();

        userEvent.click(transformationsBtn('Add transformations'));

        const transformationFields = getTransformationFieldGroups();
        const modal = document.querySelector('[data-test-transformations-modal]');

        userEvent.type(transformationFields[2].marcField.input, '');
        userEvent.type(transformationFields[0].indicator2.input, '');
        userEvent.type(transformationFields[0].subfield.input, '');

        userEvent.dblClick(screen.getByLabelText('Select all fields'));

        userEvent.click(getByRole(modal, 'button', { name: 'Save & close' }));

        return waitForElementToBeRemoved(() => container.querySelector('[data-test-transformations-modal]'));
      });
    });

    it('should display transformation value', () => {
      renderDuplicateMappingProfileRoute();

      userEvent.click(transformationsBtn('Add transformations'));

      expect(getByText(transformationListRows()[0], '900 1$12')).toBeVisible();
    });

    describe('submitting the form - success case', () => {
      beforeEach(() => {
        handleSubmitMock.mockImplementationOnce(() => Promise.resolve());
      });

      it('should call submit callback', () => {
        renderDuplicateMappingProfileRouteWithMocks();

        userEvent.click(saveAndCloseBtn());

        expect(handleSubmitMock).toHaveBeenCalled();
      });

      it('should initiate displaying of success callout', async () => {
        renderDuplicateMappingProfileRouteWithMocks();

        userEvent.click(saveAndCloseBtn());

        await waitFor(() => {
          expect(sendCalloutMock.mock.calls[0][0]).not.toHaveProperty('type');
          expect(sendCalloutMock.mock.calls[0][0].message.props.id).toBe('ui-data-export.mappingProfiles.create.successCallout');
          expect(handleSubmitNavigateMock).toHaveBeenCalled();
        });
      });
      it('should call submit callback with proper values', () => {
        renderDuplicateMappingProfileRouteWithMocks();

        userEvent.clear(nameField());
        userEvent.type(nameField(), 'Change name');
        userEvent.clear(descriptionField());
        userEvent.type(descriptionField(), 'Updated value');
        userEvent.click(saveAndCloseBtn());

        expect(nameField()).toHaveValue('Change name');
        expect(descriptionField()).toHaveValue('Updated value');
        expect(handleSubmitMock).toHaveBeenCalledWith(expect.objectContaining({
          name: 'Change name',
          description: 'Updated value',
        }));
      });
    });

    describe('submitting the form - error case', () => {
      beforeEach(() => {
        handleSubmitMock.mockImplementationOnce(() => Promise.reject());
      });

      it('should call submit callback', () => {
        renderDuplicateMappingProfileRouteWithMocks();

        userEvent.click(saveAndCloseBtn());

        expect(handleSubmitMock).toHaveBeenCalled();
      });

      it('should initiate displaying of error callout', async () => {
        renderDuplicateMappingProfileRouteWithMocks();

        userEvent.click(saveAndCloseBtn());

        await waitFor(() => {
          expect(sendCalloutMock).toBeCalledWith(
            expect.objectContaining({ type: 'error' })
          );
          expect(sendCalloutMock.mock.calls[0][0].message.props.id).toBe('ui-data-export.mappingProfiles.create.errorCallout');
        });
      });
    });
  });
});
Example #15
Source File: EditMappingProfileRoute.test.js    From ui-data-export with Apache License 2.0 4 votes vote down vote up
describe('rendering edit mapping profile page without profile data', () => {
  it('should display preloader', () => {
    renderWithIntl(
      <EditMappingProfileRouteContainer profile={null} />,
      translationsProperties
    );

    expect(screen.getByTestId('fullScreen-preloader')).toBeVisible();
  });

  describe('rendering edit mapping profile page with profile data: success scenario', () => {
    const handleCancelMock = jest.fn();
    const handleSubmitNavigateMock = jest.fn();
    const sendCalloutMock = jest.fn();

    const renderEditMappingProfileRoute = () => renderWithIntl(
      <EditMappingProfileRouteContainer allTransformations={allMappingProfilesTransformations} />,
      translationsProperties
    );

    const renderEditMappingProfileRouteWithMocks = mutator => {
      return renderWithIntl(
        <EditMappingProfileRouteContainer
          allTransformations={allMappingProfilesTransformations}
          sendCallout={sendCalloutMock}
          mutator={mutator}
          onSubmitNavigate={handleSubmitNavigateMock}
          onCancel={handleCancelMock}
          {...(mutator ? { mutator } : {})}
        />,
        translationsProperties
      );
    };

    beforeEach(() => {
      jest.clearAllMocks();
    });

    it('should display the form', () => {
      const { container } = renderEditMappingProfileRoute();
      const form = container.querySelector('[data-test-full-screen-form]');

      expect(form).toBeVisible();
    });

    it('should have correct form state', () => {
      renderEditMappingProfileRoute();

      expect(paneHeader('AP Holdings 1')).toBeVisible();
      expect(nameField()).toHaveValue(mappingProfile.name);
      expect(descriptionField()).toHaveValue(mappingProfile.description);
      expect(transformationsBtn('Edit transformations')).toBeVisible();
      expect(saveAndCloseBtn()).toBeDisabled();
      expect(recordTypeInstance()).toBeChecked();
      expect(recordTypesSRS()).not.toBeChecked();
      expect(recordTypesHoldings()).not.toBeChecked();
      expect(recordTypesItem()).not.toBeChecked();
    });

    it('should display in form proper values', async () => {
      renderEditMappingProfileRoute();

      userEvent.clear(nameField());
      userEvent.type(nameField(), 'Changed name');
      userEvent.clear(descriptionField());
      userEvent.type(descriptionField(), 'Changed description');
      userEvent.type(recordTypesHoldings(), 'instance');
      userEvent.click(saveAndCloseBtn());

      expect(nameField()).toHaveValue('Changed name');
      expect(descriptionField()).toHaveValue('Changed description');
      expect(recordTypesHoldings()).toBeChecked();
    });

    describe('clicking on cancel button', () => {
      it('should call cancel callback', () => {
        renderEditMappingProfileRouteWithMocks();

        userEvent.click(screen.getByText(/cancel/i));

        expect(handleCancelMock).toHaveBeenCalled();
      });
    });

    describe('opening transformations modal', () => {
      it('should display transformation value', () => {
        renderEditMappingProfileRoute();

        userEvent.click(transformationsBtn('Edit transformations'));

        expect(getByText(transformationListRows()[0], '900 1$12')).toBeVisible();
      });
    });

    describe('submitting the form', () => {
      it('should call submit callback', async () => {
        renderEditMappingProfileRouteWithMocks();

        userEvent.type(nameField(), 'New name');

        userEvent.click(saveAndCloseBtn());

        await waitFor(() => {
          expect(handleSubmitNavigateMock).toHaveBeenCalled();
          expect(sendCalloutMock).toHaveBeenCalled();
          expect(sendCalloutMock).not.toBeCalledWith(
            expect.objectContaining({ type: 'error' })
          );
        });
      });

      it('should initiate displaying of error callout', async () => {
        renderEditMappingProfileRouteWithMocks({ PUT: () => Promise.reject() });

        userEvent.type(nameField(), 'New name 2');

        userEvent.click(saveAndCloseBtn());

        await waitFor(() => {
          expect(sendCalloutMock).toBeCalledWith(
            expect.objectContaining({ type: 'error' })
          );
          expect(sendCalloutMock.mock.calls[0][0].message.props.id).toBe('ui-data-export.mappingProfiles.edit.errorCallout');
        });
      });
    });
  });
});
Example #16
Source File: MappingProfileDetails.test.js    From ui-data-export with Apache License 2.0 4 votes vote down vote up
describe('MappingProfileDetails', () => {
  describe('rendering details for a mapping profile which is already in use', () => {
    const renderMappingProfileDetails = () => renderWithIntl(
      <MappingProfileDetailsContainer
        allTransformations={allMappingProfilesTransformations}
        isDefaultProfile
        isProfileUsed
      />,
      translationsProperties
    );

    it('should display mapping profile details', () => {
      renderMappingProfileDetails();

      const dialog = screen.getByRole('dialog');

      expect(dialog).toBeVisible();

      const headings = within(dialog).getAllByRole('heading', { name: mappingProfileWithTransformations.name });

      headings.forEach(heading => expect(heading).toBeVisible());

      expect(within(dialog).getByRole('button', { name: /collapse all/i })).toBeVisible();

      const summary = within(dialog).getByRole('region', { name: /summary/i });
      const transformations = within(dialog).getByRole('region', { name: /transformations/i });

      expect(summary).toBeVisible();
      expect(transformations).toBeVisible();

      const labelsAndValues = [
        'Record created: 12/4/2018 1:29 AM',
        'Record last updated: 12/4/2018 1:29 AM',
        commonTranslations.name,
        'AP Holdings 1',
        translations.description,
        'AP Holdings 1 description',
        translations.outputFormat,
        'MARC',
        commonTranslations.folioRecordType,
        commonTranslations['recordTypes.holdings'],
      ];

      labelsAndValues.forEach(el => expect(within(summary).getByText(el)).toBeVisible());
    });

    it('should display correct transformations fields headers', () => {
      renderMappingProfileDetails();

      expect(screen.getByRole('columnheader', { name: translations['mappingProfiles.transformations.fieldName'] })).toBeVisible();
      expect(screen.getByRole('columnheader', { name: translations['mappingProfiles.transformations.transformation'] })).toBeVisible();
    });

    it('should display correct transformations values', () => {
      renderMappingProfileDetails();
      const transformationListRows = getAllByRole(screen.getByRole('rowgroup'), 'row');

      expect(getByText(transformationListRows[0], 'Holdings - Call number - Call number')).toBeVisible();
      expect(getByText(transformationListRows[0], '11100$a')).toBeVisible();
      expect(getByText(transformationListRows[1], 'Holdings - Notes - Action note')).toBeVisible();
      expect(getByText(transformationListRows[1], '123 1$12')).toBeVisible();
    });
    it('should display action buttons in the proper state', () => {
      const { container } = renderMappingProfileDetails();
      const actionButton = container.querySelector('[data-test-pane-header-actions-button]');
      const disableButton = container.querySelector('[data-test-delete-profile-button]');
      const duplicateButton = container.querySelector('[data-test-duplicate-profile-button]');
      const deleteButton = container.querySelector('[data-test-delete-profile-button]');

      userEvent.click(actionButton);

      expect(disableButton).toBeDisabled();
      expect(duplicateButton).toBeEnabled();
      expect(deleteButton).toBeDisabled();
    });
  });
  describe('rendering details for a mapping profile which is already in use', () => {
    const renderMappingProfileDetailsWithMapping = () => renderWithIntl(
      <MappingProfileDetailsContainer mappingProfile={mappingProfileWithoutTransformations} />,
      translationsProperties
    );

    it('should display no value in description', () => {
      const { container } = renderMappingProfileDetailsWithMapping();
      const summaryDescriptionValue = container.querySelector('[data-test-mapping-profile-description]');

      expect(getByText(summaryDescriptionValue, '-')).toBeVisible();
    });
    it('should not display delete confirmation modal', () => {
      const { container } = renderMappingProfileDetailsWithMapping();
      const deleteConfirmationModal = container.querySelector('#delete-mapping-profile-confirmation-modal');

      expect(deleteConfirmationModal).not.toBeInTheDocument();
    });
    it('should not display transformation list', () => {
      const { container } = renderMappingProfileDetailsWithMapping();
      const transformationList = container.querySelector('#mapping-profile-transformations-list');

      expect(transformationList).not.toBeInTheDocument();
    });

    it('should display action buttons enabled', () => {
      const { container } = renderMappingProfileDetailsWithMapping();
      const actionButton = container.querySelector('[data-test-pane-header-actions-button]');
      const disableButton = container.querySelector('[data-test-delete-profile-button]');
      const duplicateButton = container.querySelector('[data-test-duplicate-profile-button]');
      const deleteButton = container.querySelector('[data-test-delete-profile-button]');

      userEvent.click(actionButton);

      expect(disableButton).toBeEnabled();
      expect(duplicateButton).toBeEnabled();
      expect(deleteButton).toBeEnabled();
    });
    describe('clicking on delete profiles button', () => {
      it('should display delete confirmation modal', async () => {
        renderMappingProfileDetailsWithMapping();
        const actionButton = document.querySelector('[data-test-pane-header-actions-button]');

        userEvent.click(actionButton);

        const deleteButton = document.querySelector('[data-test-delete-profile-button]');

        userEvent.click(deleteButton);

        const modal = screen.getAllByRole('dialog').find(dialog => within(dialog).getByRole('heading', { name: /delete/i }));

        expect(modal).toBeVisible();
        userEvent.click(within(modal).getByRole('button', { name: /cancel/i }));

        await waitForElementToBeRemoved(modal);
      });
    });
  });
  describe('rendering mapping profile details in loading state', () => {
    it('should display preloader', () => {
      const { container } = renderWithIntl(<MappingProfileDetailsContainer
        mappingProfile={mappingProfileWithoutTransformations}
        isLoading
        isProfileUsed
      />,
      translationsProperties);

      expect(container.querySelector('[data-test-preloader]')).toBeVisible();
    });
  });
});
Example #17
Source File: MappingProfilesFormContainer.test.js    From ui-data-export with Apache License 2.0 4 votes vote down vote up
describe('MappingProfileFormContainer', () => {
  describe('rendering MappingProfileForm', () => {
    const onSubmitMock = jest.fn();

    beforeEach(() => {
      renderWithIntl(
        <MappingProfileFormContainer
          allTransformations={allMappingProfilesTransformations}
          onSubmit={onSubmitMock}
        />,
        translationsProperties
      );
    });

    it('should place accordion headers in correct order', () => {
      const headers = document.querySelectorAll('[data-test-headline]');

      expect(getByText(headers[0], 'Summary')).toBeVisible();
      expect(getByText(headers[1], 'Transformations')).toBeVisible();
    });

    it('should place summary fields in correct order', () => {
      const labels = document.querySelectorAll('[data-test-accordion-section] label');

      expect(getByText(labels[0], 'Name')).toBeVisible();
      expect(getByText(labels[1], 'Output format')).toBeVisible();
      expect(getByText(labels[2], 'FOLIO record type')).toBeVisible();
      expect(getByText(labels[3], 'Source record storage (entire record)')).toBeVisible();
      expect(getByText(labels[4], 'Inventory instance (selected fields)')).toBeVisible();
      expect(getByText(labels[5], 'Holdings')).toBeVisible();
      expect(getByText(labels[6], 'Item')).toBeVisible();
      expect(getByText(labels[7], 'Description')).toBeVisible();
    });

    it('should disable instance record type option when selecting SRS', () => {
      userEvent.click(screen.getByRole('checkbox', { name: 'Source record storage (entire record)' }));

      expect(screen.getByDisplayValue('INSTANCE')).toBeDisabled();
    });

    it('should disable instance record type option in transformation list when selecting SRS', () => {
      userEvent.click(screen.getByRole('checkbox', { name: 'Source record storage (entire record)' }));
      userEvent.click(screen.getByRole('button', { name: 'Add transformations' }));
      const modalRecordFilters = screen.getByRole('region', { name: 'Record type filter list' });

      expect(getByRole(modalRecordFilters, 'checkbox', { name: 'Instance' })).toBeDisabled();
    });

    it('should disable SRS record type option when selecting instance', () => {
      userEvent.click(screen.getByRole('checkbox', { name: 'Inventory instance (selected fields)' }));

      expect(screen.getByRole('checkbox', { name: 'Source record storage (entire record)' })).toBeDisabled();
    });

    it('should close transformations modal when clicking on cancel button', () => {
      userEvent.click(screen.getByRole('button', { name: 'Add transformations' }));
      const modal = document.querySelector('.modalRoot');

      userEvent.click(getByRole(modal, 'button', { name: 'Cancel' }));

      return waitForElementToBeRemoved(() => document.querySelector('.modalRoot'));
    });

    it('should display validation error when record type is not selected', () => {
      userEvent.click(screen.getByRole('checkbox', { name: 'Item' }));
      userEvent.click(screen.getByRole('checkbox', { name: 'Item' }));

      expect(getByText(document.querySelector('[data-test-folio-record-type]'),
        'Please enter a value')).toBeVisible();
    });

    it('should display correct pane title', () => {
      expect(getByText(document.querySelector('[data-test-pane-header]'), 'New field mapping profile')).toBeVisible();
    });

    it('should not display empty transformation fields', () => {
      expect(screen.getByText('No transformations found')).toBeVisible();
    });

    it('should disable save button if there are no changes', () => {
      expect(screen.getByRole('button', { name: 'Save & close' })).toBeDisabled();
    });

    it('should not mark fields as error by default', () => {
      expect(document.querySelector('[data-test-folio-record-type-error]').childElementCount).toBe(0);
      expect(screen.getByLabelText('Name*').parentElement.classList.contains('hasError')).toBeFalsy();
    });

    describe('changing transformation field value', () => {
      let transformationFields;
      let modal;
      let transformationListRows;
      let footer;
      let formSubmitButton;

      beforeEach(() => {
        userEvent.click(screen.getByRole('button', { name: 'Add transformations' }));
        userEvent.click(screen.getByLabelText('Select all fields'));

        transformationFields = getTransformationFieldGroups();
        modal = document.querySelector('.modalRoot');

        userEvent.type(transformationFields[0].marcField.input, '123');
        userEvent.type(transformationFields[0].indicator1.input, '1');
        userEvent.type(transformationFields[0].indicator2.input, '0');
        userEvent.type(transformationFields[0].subfield.input, '$r');

        userEvent.type(transformationFields[1].marcField.input, '900');
        userEvent.type(transformationFields[1].subfield.input, '$1');

        userEvent.click(getByRole(modal, 'button', { name: 'Save & close' }));

        transformationListRows = getAllByRole(screen.getByRole('rowgroup'), 'row');
        footer = document.querySelector('[data-test-pane-footer-end]');
        formSubmitButton = getByRole(footer, 'button', { name: 'Save & close' });
      });

      it('should select all and add transformations with values', () => {
        expect(transformationListRows.length).toBe(2);
        expect(getByText(transformationListRows[0], '12310$r')).toBeVisible();
        expect(getByText(transformationListRows[1], '900 $1')).toBeVisible();
      });

      it('should enable submit button', () => {
        expect(formSubmitButton).not.toBeDisabled();
      });

      it('should display validation error when transformations do not match record type', () => {
        const folioRecordTypeContainer = document.querySelector('[data-test-folio-record-type]');

        userEvent.type(screen.getByLabelText('Name*'), 'Name');
        userEvent.click(getByRole(folioRecordTypeContainer, 'checkbox', { name: 'Item' }));

        userEvent.click(getByRole(footer, 'button', { name: 'Save & close' }));

        expect(getByText(document.querySelector('[data-test-folio-record-type]'),
          'Selected record types do not match specified transformations')).toBeVisible();
      });

      it('should disable submit button after clearing transformations', () => {
        userEvent.click(screen.getByRole('button', { name: 'Add transformations' }));
        userEvent.click(screen.getByLabelText('Select all fields'));
        userEvent.click(getByRole(modal, 'button', { name: 'Save & close' }));

        expect(formSubmitButton).toBeDisabled();
      });

      it('should not display validation for record types when SRS and holdings types are checked', () => {
        const folioRecordTypeContainer = document.querySelector('[data-test-folio-record-type]');

        userEvent.type(screen.getByLabelText('Name*'), 'Name');
        userEvent.click(getByRole(folioRecordTypeContainer, 'checkbox', { name: 'Holdings' }));
        userEvent.click(screen.getByRole('checkbox', { name: 'Source record storage (entire record)' }));
        userEvent.click(getByRole(footer, 'button', { name: 'Save & close' }));

        expect(queryByText(document.querySelector('[data-test-folio-record-type]'),
          'Selected record types do not match specified transformations')).toBeNull();
        expect(onSubmitMock).toBeCalled();
      });

      describe('reopening transformation modal', () => {
        beforeEach(async () => {
          userEvent.click(screen.getByRole('button', { name: 'Add transformations' }));
        });

        it('should display proper amount of found transformations', () => {
          const modalHeader = document.querySelector('[data-test-pane-header-sub]');

          expect(getByText(modalHeader, '2 fields found')).toBeVisible();
        });

        it('should display proper total selected count', () => {
          const totalSelected = document.querySelector('[data-test-transformations-total-selected]');

          expect(getByText(totalSelected, 'Total selected: 2')).toBeVisible();
        });

        it('should have correct placeholders', () => {
          expect(transformationFields.length).toEqual(2);

          expect(queryByPlaceholderText(transformationFields[1].marcField.container, '900')).toBeNull();
          expect(queryByPlaceholderText(transformationFields[1].indicator1.container, '0')).toBeNull();
          expect(queryByPlaceholderText(transformationFields[1].indicator2.container, '0')).toBeNull();
          expect(queryByPlaceholderText(transformationFields[1].subfield.container, '$a')).toBeNull();
        });

        it('should have correct placeholders after the first transformation is selected and hidden after the selected items filter is unchecked', () => {
          userEvent.click(screen.getAllByRole('checkbox', { name: 'Select field' })[0]);
          userEvent.click(screen.getByRole('checkbox', { name: 'Selected' }));

          transformationFields = getTransformationFieldGroups();

          expect(transformationFields.length).toEqual(1);

          expect(queryByPlaceholderText(transformationFields[0].marcField.container, '900')).toBeNull();
          expect(queryByPlaceholderText(transformationFields[0].indicator1.container, '0')).toBeNull();
          expect(queryByPlaceholderText(transformationFields[0].indicator2.container, '0')).toBeNull();
          expect(queryByPlaceholderText(transformationFields[0].subfield.container, '$a')).toBeNull();
        });

        it('should display correct transformation fields values', () => {
          expect(transformationFields[0].marcField.input.value).toBe('123');
          expect(transformationFields[0].indicator1.input.value).toBe('1');
          expect(transformationFields[0].indicator2.input.value).toBe('0');
          expect(transformationFields[0].subfield.input.value).toBe('$r');

          expect(transformationFields[1].marcField.input.value).toBe('900');
          expect(transformationFields[1].indicator1.input.value).toBe('');
          expect(transformationFields[1].indicator2.input.value).toBe('');
          expect(transformationFields[1].indicator2.input.value).toBe('');
          expect(transformationFields[1].subfield.input.value).toBe('$1');
        });

        describe('unchecking transformation, clicking cancel and reopening modal', () => {
          it('should display correct selected field count', () => {
            const selectTransformationCheckboxes = screen.getAllByLabelText('Select field');

            userEvent.click(selectTransformationCheckboxes[0]);
            userEvent.click(getByRole(modal, 'button', { name: 'Cancel' }));
            userEvent.click(screen.getByRole('button', { name: 'Add transformations' }));

            const totalSelected = document.querySelector('[data-test-transformations-total-selected]');

            expect(getByText(totalSelected, 'Total selected: 2')).toBeVisible();
          });
        });
      });
    });
  });
});
Example #18
Source File: MappingProfilesTransformationsModal.test.js    From ui-data-export with Apache License 2.0 4 votes vote down vote up
describe('MappingProfilesTransformationsModal', () => {
  describe('rendering mapping profile transformations modal', () => {
    const onSubmitMock = jest.fn();
    let modal;

    beforeEach(() => {
      renderWithIntl(
        <MappingProfilesTransformationModalContainer
          onSubmit={onSubmitMock}
        />,
        translationsProperties
      );
      modal = document.querySelector('[data-test-transformations-modal]');
    });

    afterEach(() => {
      jest.clearAllMocks();
    });

    it('should display transformations modal', () => {
      expect(modal).toBeInTheDocument();
    });

    it('should display search pane', () => {
      expect(modal.querySelector('[data-test-transformations-search-pane]')).toBeInTheDocument();
    });

    it('should display results pane', () => {
      const resultsPane = modal.querySelector('[data-test-transformations-results-pane]');

      expect(resultsPane).toBeInTheDocument();
      expect(getByText(resultsPane, 'Transformations')).toBeInTheDocument();
      expect(getByText(resultsPane, `${initialValues.transformations.length} fields found`)).toBeInTheDocument();
    });

    it('should display total selected count', () => {
      expect(getByText(modal, 'Total selected: 0')).toBeInTheDocument();
    });

    it('should display search form', () => {
      expect(modal.querySelector('[data-test-transformations-search-form]')).toBeInTheDocument();
    });

    it('should display correct folio record types', () => {
      const checkboxes = getAllByRole(modal, 'checkbox');

      expect(checkboxes[0].value).toBe('INSTANCE');
      expect(checkboxes[1].value).toBe('HOLDINGS');
      expect(checkboxes[2].value).toBe('ITEM');
    });

    it('should display cancel button', () => {
      expect(getByRole(modal, 'button', { name: 'Cancel' })).toBeInTheDocument();
    });

    it('should display save button', () => {
      expect(getByRole(modal, 'button', { name: 'Save & close' })).toBeInTheDocument();
    });

    describe('filling transformation values', () => {
      let transformationFields;
      let submitButton;

      beforeEach(() => {
        transformationFields = getTransformationFieldGroups();
        submitButton = getByRole(modal, 'button', { name: 'Save & close' });
        userEvent.type(transformationFields[0].marcField.input, '123');
        userEvent.type(transformationFields[0].indicator1.input, '1');
        userEvent.type(transformationFields[0].indicator2.input, '0');
        userEvent.type(transformationFields[0].subfield.input, '$r');
      });

      it('should enable submit button', () => {
        expect(submitButton).not.toBeDisabled();
      });

      it('should validate fields as valid and initiate modal submit', () => {
        userEvent.click(submitButton);

        expect(onSubmitMock).toBeCalled();
      });

      describe('selecting all fields and clicking submit', () => {
        beforeEach(() => {
          userEvent.click(screen.getByLabelText('Select all fields'));
          userEvent.click(submitButton);
          transformationFields = getTransformationFieldGroups();
        });

        it('should not initiate modal submit', () => {
          expect(onSubmitMock).not.toBeCalled();
        });

        it('should disable submit button', () => {
          expect(submitButton).toBeDisabled();
        });

        it('should validate instance record type transformation as valid (instances can be empty)', () => {
          expect(transformationFields[1].isInvalid).toBe(false);
        });

        it('should validate item record type transformation and mark marcField as invalid', () => {
          expect(transformationFields[2].isInvalid).toBe(true);
          expect(transformationFields[2].marcField.isInvalid).toBe(true);
          expect(transformationFields[2].indicator1.isInvalid).toBe(false);
          expect(transformationFields[2].indicator2.isInvalid).toBe(false);
          expect(transformationFields[2].subfield.isInvalid).toBe(false);
        });

        describe('filling empty invalid field with invalid transformation', () => {
          beforeEach(() => {
            userEvent.type(transformationFields[2].subfield.input, '12');
            userEvent.click(submitButton);
            transformationFields = getTransformationFieldGroups();
          });

          it('should mark transformation field group, marc field and subfield as invalid', () => {
            expect(transformationFields[2].isInvalid).toBe(true);
            expect(transformationFields[2].marcField.isInvalid).toBe(true);
            expect(transformationFields[2].indicator1.isInvalid).toBe(false);
            expect(transformationFields[2].indicator2.isInvalid).toBe(false);
            expect(transformationFields[2].subfield.isInvalid).toBe(true);
          });

          describe('changing marc field', () => {
            beforeEach(() => {
              userEvent.type(transformationFields[2].marcField.input, '900');
              transformationFields = getTransformationFieldGroups();
            });

            it('should mark marc field as valid and keep subfield and transformation group as invalid', () => {
              expect(transformationFields[2].isInvalid).toBe(true);
              expect(transformationFields[2].marcField.isInvalid).toBe(false);
              expect(transformationFields[2].subfield.isInvalid).toBe(true);
            });

            it('should mark subfield as valid as well as transformation group after addressing every invalid field', () => {
              userEvent.type(transformationFields[2].subfield.input, '$12');
              transformationFields = getTransformationFieldGroups();

              expect(transformationFields[2].isInvalid).toBe(false);
              expect(transformationFields[2].subfield.isInvalid).toBe(false);
            });
          });
        });

        describe('filling empty invalid field with valid transformation', () => {
          beforeEach(() => {
            userEvent.type(transformationFields[2].marcField.input, '900');
            userEvent.type(transformationFields[2].indicator1.input, 'r');
            userEvent.type(transformationFields[2].indicator2.input, '1');
            userEvent.type(transformationFields[2].subfield.input, '$90');
            userEvent.click(submitButton);
          });

          it('should validate fields as valid and initiate modal submit', () => {
            transformationFields = getTransformationFieldGroups();
            expect(transformationFields[2].marcField.isInvalid).toBe(false);
            expect(transformationFields[2].indicator1.isInvalid).toBe(false);
            expect(transformationFields[2].indicator2.isInvalid).toBe(false);
            expect(transformationFields[2].subfield.isInvalid).toBe(false);
            expect(onSubmitMock).toBeCalledWith([{
              enabled: true,
              fieldId: 'field1',
              rawTransformation: {
                marcField: '123',
                indicator1: '1',
                indicator2: '0',
                subfield: '$r',
              },
              recordType: 'HOLDINGS',
              transformation: '12310$r',
            }, {
              enabled: true,
              fieldId: 'field2',
              recordType: 'INSTANCE',
              transformation: '',
            }, {
              enabled: true,
              fieldId: 'field3',
              rawTransformation: {
                marcField: '900',
                indicator1: 'r',
                indicator2: '1',
                subfield: '$90',
              },
              recordType: 'ITEM',
              transformation: '900r1$90',
            }]);
          });
        });
      });
    });
  });
});
Example #19
Source File: InterfacesTab.test.js    From cockpit-wicked with GNU General Public License v2.0 4 votes vote down vote up
describe('InterfacesTab', () => {
    const getConnectionsMock = jest.fn(() => Promise.resolve([]));
    const getInterfacesMock = jest.fn(() => Promise.resolve([eth0]));
    const addConnectionMock = jest.fn(() => Promise.resolve(createConnection({ name: 'eth0' })));
    const reloadConnectionMock = jest.fn(() => Promise.resolve(true));
    const eth0 = createInterface({ name: 'eth0', link: false });

    beforeAll(() => {
        resetClient();
        NetworkClient.mockImplementation(() => {
            return {
                getConnections: getConnectionsMock,
                getInterfaces: getInterfacesMock,
                addConnection: addConnectionMock,
                reloadConnection: reloadConnectionMock,
                onInterfaceChange: jest.fn()
            };
        });
    });

    test('configure an unconfigured interface', async () => {
        act(() => {
            customRender(<InterfacesTab />);
        });

        expect(await screen.findByText('eth0')).toBeInTheDocument();

        // open the dialog and apply the default configuration
        const expandButton = screen.getByRole('button', { name: 'Details' });
        userEvent.click(expandButton);
        const configureLink = screen.getByRole('link', { name: 'Not configured' });
        userEvent.click(configureLink);
        const button = await screen.findByRole('button', { name: 'Apply' });
        userEvent.click(button);

        // the interface is finally being configured
        expect(await screen.findByText('Configuring')).toBeInTheDocument();
    });

    test('handles an error when configuring an interface', async () => {
        const error = new Error('Something went wrong');
        reloadConnectionMock.mockImplementation(() => Promise.reject(error));

        act(() => {
            customRender(<InterfacesTab />);
        });

        expect(await screen.findByText('eth0')).toBeInTheDocument();

        // open the dialog and apply the default configuration
        const expandButton = screen.getByRole('button', { name: 'Details' });
        userEvent.click(expandButton);
        const configureLink = screen.getByRole('link', { name: 'Not configured' });
        userEvent.click(configureLink);
        const button = await screen.findByRole('button', { name: 'Apply' });
        userEvent.click(button);

        // notify the user about the problem
        expect(await screen.findByText(/Something went wrong/i)).toBeInTheDocument();
    });

    test('the unmanaged interfaces list is not shown when it is empty', async () => {
        act(() => {
            customRender(<InterfacesTab />);
        });

        expect(await screen.findByText('eth0')).toBeInTheDocument();
        const table = screen.queryByRole('grid', { name: /unmanaged/i });
        expect(table).toBeNull();
    });

    test('not managed interfaces are shown in the unmanaged list', async () => {
        const virbr0 = createInterface({ name: 'virbr0', link: true, managed: false, virtual: true, type: 'br' });
        getInterfacesMock.mockImplementation(() => Promise.resolve([eth0, virbr0]));

        act(() => {
            customRender(<InterfacesTab />);
        });

        expect(await screen.findByText('eth0')).toBeInTheDocument();
        const table = screen.getByRole('grid', { name: /unmanaged/i });
        expect(getByText(table, 'virbr0')).toBeInTheDocument();
    });
});