import React from 'react'; import { waitForElementToBeRemoved } from '@testing-library/dom'; import { act, cleanup, fireEvent, render, RenderResult, } from '@testing-library/react'; import { constructProjectURL, dataFixtures, urlFixtures } from '../../data'; import ProjectSelect from './ProjectSelect'; // data const { currentProject, projects } = dataFixtures; const mongoSelectUrls = urlFixtures.mongoSelect; describe('packages/mongo-select/ProjectSelect', () => { let getByTestId: RenderResult['getByTestId']; let queryByTestId: RenderResult['queryByTestId']; let queryAllByTestId: RenderResult['queryAllByTestId']; afterEach(() => { jest.restoreAllMocks(); cleanup(); }); describe('ProjectSelect', () => { const renderComponent = (props = {}) => { ({ getByTestId, queryByTestId, queryAllByTestId } = render( , )); }; describe('when rendered with default props', () => { beforeEach(renderComponent); it('displays the project select trigger with the current project name', () => { expect( getByTestId('project-select-active-project').textContent, ).toEqual('Demo Project 1'); }); it('sets the "aria-expanded" attribute is set to false', () => { expect( getByTestId('project-select-trigger').getAttribute('aria-expanded'), ).toBe('false'); }); describe('when clicking the current project trigger', () => { beforeEach(() => { fireEvent.click(getByTestId('project-select-trigger')); }); it('sets the "aria-expanded" attribute is set to false', () => { expect( getByTestId('project-select-trigger').getAttribute('aria-expanded'), ).toBe('true'); }); it('displays a placeholder without an existing value', () => { expect( getByTestId('project-filter-input').getAttribute('placeholder'), ).toContain('Search for a Project...'); }); it('displays two projects', () => { const projectResults = queryAllByTestId('project-option'); expect(projectResults.length).toEqual(2); }); it('displays the correct names of each project', () => { const projectResults = queryAllByTestId('project-option'); expect(projectResults[0].textContent).toContain('Demo Project'); expect(projectResults[1].textContent).toContain('Demo Project 2'); }); it('displays the correct link to projects of each result', () => { const projectResults = queryAllByTestId('project-option'); expect((projectResults[0] as HTMLAnchorElement).href).toBe( 'https://cloud.mongodb.com/v2#/fakeProjectId1', ); expect((projectResults[1] as HTMLAnchorElement).href).toBe( 'https://cloud.mongodb.com/v2#/fakeProjectId2', ); }); it('indicates the current project', () => { const projectResults = queryAllByTestId('project-option'); const currentResult = projectResults.find( result => result.getAttribute('aria-current') === 'true', ); expect(currentResult).toBeInTheDocument(); }); }); }); describe('when a user filters projects', () => { beforeEach(renderComponent); beforeEach(() => { fireEvent.click(getByTestId('project-select-trigger')); }); it('displays one project when only one matches the search', () => { const input = getByTestId('project-filter-input'); fireEvent.change(input, { target: { value: '1' }, }); expect(queryAllByTestId('project-option').length).toBe(1); }); it('displays no projects when none matches the search', () => { const input = getByTestId('project-filter-input'); fireEvent.change(input, { target: { value: 'xx' }, }); expect(queryAllByTestId('project-option').length).toBe(0); }); it('when closing the menu the filter value is reset', async () => { // Close menu act(() => { // For some reason this causes a navigation and a console error. // I can't figure out how or why yet document.body.dispatchEvent( new MouseEvent('click', { bubbles: true }), ); }); // Need to wait for the UI to update as clicking on the orgTrigger so rapidly causes // React to coalesce the events await waitForElementToBeRemoved(() => queryByTestId('project-filter-input'), ); fireEvent.click(getByTestId('project-select-trigger')); expect(getByTestId('project-filter-input').innerHTML).toEqual(''); }); }); describe('when the onChange prop is set', () => { const onChange = jest.fn(); beforeEach(() => renderComponent({ onChange })); it('does not filter the projects and calls the onChange callback', () => { fireEvent.click(getByTestId('project-select-trigger')); const input = getByTestId('project-filter-input'); fireEvent.change(input, { target: { value: '1' }, }); expect(onChange).toHaveBeenCalledTimes(1); expect(queryAllByTestId('project-option').length).toBe(2); }); }); }); // eslint-disable-next-line jest/no-disabled-tests describe.skip('types work as expected', () => { // eslint-disable-next-line jest/expect-expect test('does not error when only ProjectSelect values are passed to url prop', () => { 'string'} urls={{ viewAllProjects: 'string', newProject: 'string' }} />; }); }); });