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' }}
/>;
});
});
});