import {mountWithTheme} from 'sentry-test/enzyme';
import {act} from 'sentry-test/reactTestingLibrary';
import {findOption, openMenu, selectByValueAsync} from 'sentry-test/select-new';
import MemberListStore from 'sentry/stores/memberListStore';
import ProjectsStore from 'sentry/stores/projectsStore';
import TeamStore from 'sentry/stores/teamStore';
import RuleBuilder from 'sentry/views/settings/project/projectOwnership/ruleBuilder';
describe('RuleBuilder', function () {
const organization = TestStubs.Organization();
let project;
let handleAdd;
const USER_1 = TestStubs.User({
id: '1',
name: 'Jane Bloggs',
email: 'janebloggs@example.com',
user: {
id: '1',
name: 'Jane Bloggs',
email: 'janebloggs@example.com',
},
});
const USER_2 = TestStubs.User({
id: '2',
name: 'John Smith',
email: 'johnsmith@example.com',
user: {
id: '2',
name: 'John Smith',
email: 'johnsmith@example.com',
},
});
const TEAM_1 = TestStubs.Team({
id: '3',
name: 'COOL TEAM',
slug: 'cool-team',
});
// This team is in project
const TEAM_2 = TestStubs.Team({
id: '4',
name: 'TEAM NOT IN PROJECT',
slug: 'team-not-in-project',
});
beforeEach(function () {
// User in project
MemberListStore.loadInitialData([USER_1]);
// All teams
jest.spyOn(TeamStore, 'getAll').mockImplementation(() => [TEAM_1, TEAM_2]);
handleAdd = jest.fn();
project = TestStubs.Project({
// Teams in project
teams: [TEAM_1],
});
act(() => ProjectsStore.loadInitialData([project]));
jest.spyOn(ProjectsStore, 'getBySlug').mockImplementation(() => project);
MockApiClient.clearMockResponses();
MockApiClient.addMockResponse({
url: '/organizations/org-slug/members/',
body: [USER_1, USER_2],
});
});
afterEach(function () {});
it('renders', async function () {
const wrapper = mountWithTheme(
);
await tick();
wrapper.update();
const add = wrapper.find('AddButton');
add.simulate('click');
expect(handleAdd).not.toHaveBeenCalled();
const text = wrapper.find('BuilderInput');
text.simulate('change', {target: {value: 'some/path/*'}});
expect(wrapper.find('AddButton').prop('disabled')).toBe(true);
add.simulate('click');
expect(handleAdd).not.toHaveBeenCalled();
// Select the first item in the list.
await selectByValueAsync(wrapper, 'user:1', {name: 'owners', control: true});
wrapper.update();
expect(wrapper.find('AddButton').prop('disabled')).toBe(false);
add.simulate('click');
expect(handleAdd).toHaveBeenCalled();
// This is because after selecting, react-select (async) reloads
await tick();
wrapper.update();
expect(wrapper.find(RuleBuilder)).toSnapshot();
});
it('renders with suggestions', async function () {
const wrapper = mountWithTheme(
);
// Open the menu so we can do some assertions.
openMenu(wrapper, {name: 'owners', control: true});
await tick();
wrapper.update();
// Should have all 4 users/teams listed
expect(wrapper.find('IdBadge')).toHaveLength(4);
// Should have 1 user not in project and 1 team not in project
expect(wrapper.find('DisabledLabel IdBadge')).toHaveLength(2);
// Team not in project should not be selectable
expect(wrapper.find('DisabledLabel IdBadge').at(0).prop('team').id).toBe('4');
// John Smith should not be selectable
expect(wrapper.find('DisabledLabel IdBadge').at(1).prop('user').id).toBe('2');
// Enter to select Jane Bloggs
findOption(wrapper, {value: 'user:1'}, {name: 'owners', control: true})
.at(0)
.simulate('click');
const ruleCandidate = wrapper.find('RuleCandidate').first();
ruleCandidate.simulate('click');
// This is because after selecting, react-select (async) reloads
await tick();
wrapper.update();
expect(wrapper.find(RuleBuilder)).toSnapshot();
wrapper.find('AddButton').simulate('click');
expect(handleAdd).toHaveBeenCalled();
});
});