123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- import React from 'react';
- import {mount} from 'enzyme';
- import ProjectSelector from 'app/components/projectSelector';
- import ProjectsStore from 'app/stores/projectsStore';
- describe('ProjectSelector', function() {
- const testTeam = TestStubs.Team({
- id: 'test-team',
- slug: 'test-team',
- isMember: true,
- });
- const testProject = TestStubs.Project({
- id: 'test-project',
- slug: 'test-project',
- isBookmarked: true,
- isMember: true,
- teams: [testTeam],
- });
- const anotherProject = TestStubs.Project({
- id: 'another-project',
- slug: 'another-project',
- isMember: true,
- teams: [testTeam],
- });
- const mockOrg = TestStubs.Organization({
- id: 'org',
- slug: 'org',
- teams: [testTeam],
- projects: [testProject, anotherProject],
- features: ['new-teams'],
- access: [],
- });
- const routerContext = TestStubs.routerContext([{organization: mockOrg}]);
- const openMenu = wrapper =>
- wrapper.find('[data-test-id="test-actor"]').simulate('click');
- const actorRenderer = jest.fn(() => <div data-test-id="test-actor" />);
- const props = {
- organization: mockOrg,
- projectId: '',
- children: actorRenderer,
- };
- beforeEach(function() {
- ProjectsStore.loadInitialData(mockOrg.projects);
- });
- it('should show empty message with no projects button, when no projects, and has no "project:write" access', function() {
- const wrapper = mount(
- <ProjectSelector
- {...props}
- organization={{
- id: 'org',
- slug: 'org-slug',
- teams: [],
- projects: [],
- access: [],
- }}
- />,
- routerContext
- );
- ProjectsStore.loadInitialData([]);
- openMenu(wrapper);
- expect(wrapper.find('EmptyMessage').prop('children')).toBe('You have no projects');
- // Should not have "Create Project" button
- expect(wrapper.find('CreateProjectButton')).toHaveLength(0);
- });
- it('should show empty message and create project button, when no projects and has "project:write" access', function() {
- const wrapper = mount(
- <ProjectSelector
- {...props}
- organization={{
- id: 'org',
- slug: 'org-slug',
- teams: [],
- projects: [],
- access: ['project:write'],
- }}
- />,
- routerContext
- );
- ProjectsStore.loadInitialData([]);
- openMenu(wrapper);
- expect(wrapper.find('EmptyMessage').prop('children')).toBe('You have no projects');
- // Should not have "Create Project" button
- expect(wrapper.find('CreateProjectButton')).toHaveLength(1);
- });
- it('lists projects and has filter', function() {
- const wrapper = mount(<ProjectSelector {...props} />, routerContext);
- openMenu(wrapper);
- expect(wrapper.find('AutoCompleteItem')).toHaveLength(2);
- });
- it('can filter projects by project name', function() {
- const wrapper = mount(<ProjectSelector {...props} />, routerContext);
- openMenu(wrapper);
- wrapper.find('StyledInput').simulate('change', {target: {value: 'TEST'}});
- const result = wrapper.find('AutoCompleteItem ProjectBadge');
- expect(result).toHaveLength(1);
- expect(result.prop('project').slug).toBe('test-project');
- });
- it('does not close dropdown when input is clicked', async function() {
- const wrapper = mount(<ProjectSelector {...props} />, routerContext);
- openMenu(wrapper);
- wrapper.find('StyledInput').simulate('click');
- await tick();
- wrapper.update();
- expect(wrapper.find('DropdownMenu').prop('isOpen')).toBe(true);
- });
- it('closes dropdown when project is selected', function() {
- const wrapper = mount(<ProjectSelector {...props} />, routerContext);
- openMenu(wrapper);
- // Select first project
- wrapper
- .find('AutoCompleteItem')
- .first()
- .simulate('click');
- expect(wrapper.find('DropdownMenu').prop('isOpen')).toBe(false);
- });
- it('calls callback when project is selected', function() {
- const mock = jest.fn();
- const wrapper = mount(<ProjectSelector {...props} onSelect={mock} />, routerContext);
- openMenu(wrapper);
- // Select first project
- wrapper
- .find('AutoCompleteItem')
- .first()
- .simulate('click');
- expect(mock).toHaveBeenCalledWith(
- expect.objectContaining({
- slug: 'test-project',
- })
- );
- });
- it('shows empty filter message when filtering has no results', function() {
- const wrapper = mount(<ProjectSelector {...props} />, routerContext);
- openMenu(wrapper);
- wrapper.find('StyledInput').simulate('change', {target: {value: 'Foo'}});
- expect(wrapper.find('EmptyMessage').prop('children')).toBe('No projects found');
- });
- it('does not call `onSelect` when using multi select', function() {
- const mock = jest.fn();
- const wrapper = mount(
- <ProjectSelector {...props} multi onSelect={mock} />,
- routerContext
- );
- openMenu(wrapper);
- // Select first project
- wrapper
- .find('CheckboxWrapper')
- .first()
- .simulate('click');
- // onSelect callback should NOT be called
- expect(mock).not.toHaveBeenCalled();
- });
- it('calls `onMultiSelect` and render prop when using multi select as an uncontrolled component', async function() {
- const mock = jest.fn();
- const wrapper = mount(
- <ProjectSelector {...props} multi onMultiSelect={mock} />,
- routerContext
- );
- openMenu(wrapper);
- // Select first project
- wrapper
- .find('CheckboxWrapper')
- .at(0)
- .simulate('click', {target: {checked: true}});
- expect(mock).toHaveBeenLastCalledWith(
- [
- expect.objectContaining({
- slug: 'test-project',
- }),
- ],
- expect.anything()
- );
- expect(actorRenderer).toHaveBeenLastCalledWith(
- expect.objectContaining({
- selectedProjects: [expect.objectContaining({slug: 'test-project'})],
- })
- );
- expect(
- Array.from(
- wrapper
- .find('ProjectSelectorItem')
- .filterWhere(p => p.prop('isChecked'))
- .map(p => p.prop('project').slug)
- )
- ).toEqual(['test-project']);
- // second project
- wrapper
- .find('CheckboxWrapper')
- .at(1)
- .simulate('click', {target: {checked: true}});
- expect(mock).toHaveBeenLastCalledWith(
- [
- expect.objectContaining({
- slug: 'test-project',
- }),
- expect.objectContaining({
- slug: 'another-project',
- }),
- ],
- expect.anything()
- );
- expect(actorRenderer).toHaveBeenLastCalledWith(
- expect.objectContaining({
- selectedProjects: [
- expect.objectContaining({slug: 'test-project'}),
- expect.objectContaining({slug: 'another-project'}),
- ],
- })
- );
- expect(
- Array.from(
- wrapper
- .find('ProjectSelectorItem')
- .filterWhere(p => p.prop('isChecked'))
- .map(p => p.prop('project').slug)
- )
- ).toEqual(['test-project', 'another-project']);
- // Can unselect item
- wrapper
- .find('CheckboxWrapper')
- .at(1)
- .simulate('click', {target: {checked: false}});
- expect(mock).toHaveBeenLastCalledWith(
- [
- expect.objectContaining({
- slug: 'test-project',
- }),
- ],
- expect.anything()
- );
- expect(actorRenderer).toHaveBeenLastCalledWith(
- expect.objectContaining({
- selectedProjects: [expect.objectContaining({slug: 'test-project'})],
- })
- );
- expect(
- Array.from(
- wrapper
- .find('ProjectSelectorItem')
- .filterWhere(p => p.prop('isChecked'))
- .map(p => p.prop('project').slug)
- )
- ).toEqual(['test-project']);
- });
- it('displays multi projects', function() {
- const project = TestStubs.Project();
- const multiProjectProps = {...props, multiProjects: [project]};
- const wrapper = mount(<ProjectSelector {...multiProjectProps} />, routerContext);
- openMenu(wrapper);
- expect(wrapper.find('AutoCompleteItem')).toHaveLength(1);
- expect(wrapper.text()).not.toContain("Projects I don't belong to");
- });
- it('displays multi projects with non member projects', function() {
- const project = TestStubs.Project({id: '1'});
- const nonMemberProject = TestStubs.Project({id: '2'});
- const multiProjectProps = {
- ...props,
- multiProjects: [project],
- nonMemberProjects: [nonMemberProject],
- };
- const wrapper = mount(<ProjectSelector {...multiProjectProps} />, routerContext);
- openMenu(wrapper);
- expect(wrapper.text()).toContain("Projects I don't belong to");
- expect(wrapper.find('AutoCompleteItem')).toHaveLength(2);
- });
- });
|