import {mountWithTheme} from 'sentry-test/enzyme';
import {act} from 'sentry-test/reactTestingLibrary';
import * as TeamKeyTransactionManager from 'sentry/components/performance/teamKeyTransactionsManager';
import ProjectsStore from 'sentry/stores/projectsStore';
import TeamStore from 'sentry/stores/teamStore';
import TeamKeyTransactionField from 'sentry/utils/discover/teamKeyTransactionField';
async function clickTeamKeyTransactionDropdown(wrapper) {
wrapper.find('IconStar').simulate('click');
await tick();
wrapper.update();
}
describe('TeamKeyTransactionField', function () {
const organization = TestStubs.Organization();
const teams = [
TestStubs.Team({id: '1', slug: 'team1', name: 'Team 1'}),
TestStubs.Team({id: '2', slug: 'team2', name: 'Team 2'}),
];
const project = TestStubs.Project({teams});
beforeEach(function () {
MockApiClient.clearMockResponses();
act(() => ProjectsStore.loadInitialData([project]));
act(() => TeamStore.loadInitialData(teams));
});
it('renders with all teams checked', async function () {
const getTeamKeyTransactionsMock = MockApiClient.addMockResponse({
method: 'GET',
url: `/organizations/${organization.slug}/key-transactions-list/`,
body: teams.map(({id}) => ({
team: id,
count: 1,
keyed: [{project_id: String(project.id), transaction: 'transaction'}],
})),
});
const wrapper = mountWithTheme(
);
await tick();
wrapper.update();
expect(getTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
expect(wrapper.find('IconStar').exists()).toBeTruthy();
expect(wrapper.find('IconStar').props().isSolid).toBeTruthy();
clickTeamKeyTransactionDropdown(wrapper);
// header should show the checked state
const header = wrapper.find('DropdownMenuHeader');
expect(header.exists()).toBeTruthy();
expect(header.find('CheckboxFancy').props().isChecked).toBeTruthy();
expect(header.find('CheckboxFancy').props().isIndeterminate).toBeFalsy();
// all teams should be checked
const entries = wrapper.find('DropdownMenuItem');
expect(entries.length).toBe(2);
entries.forEach((entry, i) => {
expect(entry.text()).toEqual(teams[i].slug);
expect(entry.find('CheckboxFancy').props().isChecked).toBeTruthy();
});
});
it('renders with some teams checked', async function () {
const getTeamKeyTransactionsMock = MockApiClient.addMockResponse({
method: 'GET',
url: `/organizations/${organization.slug}/key-transactions-list/`,
body: teams.map(({id}) => ({
team: id,
count: id === teams[0].id ? 1 : 0,
keyed:
id === teams[0].id
? [{project_id: String(project.id), transaction: 'transaction'}]
: [],
})),
});
const wrapper = mountWithTheme(
);
await tick();
wrapper.update();
expect(getTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
expect(wrapper.find('IconStar').exists()).toBeTruthy();
expect(wrapper.find('IconStar').props().isSolid).toBeTruthy();
clickTeamKeyTransactionDropdown(wrapper);
// header should show the indeterminate state
const header = wrapper.find('DropdownMenuHeader');
expect(header.exists()).toBeTruthy();
expect(header.find('CheckboxFancy').props().isChecked).toBeFalsy();
expect(header.find('CheckboxFancy').props().isIndeterminate).toBeTruthy();
// all teams should be checked
const entries = wrapper.find('DropdownMenuItem');
expect(entries.length).toBe(2);
entries.forEach((entry, i) => {
expect(entry.text()).toEqual(teams[i].slug);
});
expect(entries.at(0).find('CheckboxFancy').props().isChecked).toBeTruthy();
expect(entries.at(1).find('CheckboxFancy').props().isChecked).toBeFalsy();
});
it('renders with no teams checked', async function () {
const getTeamKeyTransactionsMock = MockApiClient.addMockResponse({
method: 'GET',
url: `/organizations/${organization.slug}/key-transactions-list/`,
body: teams.map(({id}) => ({
team: id,
count: 0,
keyed: [],
})),
});
const wrapper = mountWithTheme(
);
await tick();
wrapper.update();
expect(getTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
expect(wrapper.find('IconStar').exists()).toBeTruthy();
expect(wrapper.find('IconStar').props().isSolid).toBeFalsy();
clickTeamKeyTransactionDropdown(wrapper);
// header should show the unchecked state
const header = wrapper.find('DropdownMenuHeader');
expect(header.exists()).toBeTruthy();
expect(header.find('CheckboxFancy').props().isChecked).toBeFalsy();
expect(header.find('CheckboxFancy').props().isIndeterminate).toBeFalsy();
// all teams should be unchecked
const entries = wrapper.find('DropdownMenuItem');
expect(entries.length).toBe(2);
entries.forEach((entry, i) => {
expect(entry.text()).toEqual(teams[i].slug);
expect(entry.find('CheckboxFancy').props().isChecked).toBeFalsy();
});
});
it('should be able to check one team', async function () {
MockApiClient.addMockResponse({
method: 'GET',
url: `/organizations/${organization.slug}/key-transactions-list/`,
body: teams.map(({id}) => ({
team: id,
count: 0,
keyed: [],
})),
});
const postTeamKeyTransactionsMock = MockApiClient.addMockResponse({
method: 'POST',
url: '/organizations/org-slug/key-transactions/',
body: [],
match: [
MockApiClient.matchQuery({project: [project.id]}),
MockApiClient.matchData({team: [teams[0].id], transaction: 'transaction'}),
],
});
const wrapper = mountWithTheme(
);
await tick();
wrapper.update();
clickTeamKeyTransactionDropdown(wrapper);
expect(
wrapper.find('DropdownMenuItem CheckboxFancy').first().props().isChecked
).toBeFalsy();
wrapper.find('DropdownMenuItem CheckboxFancy').first().simulate('click');
await tick();
wrapper.update();
expect(
wrapper.find('DropdownMenuItem CheckboxFancy').first().props().isChecked
).toBeTruthy();
expect(postTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
});
it('should be able to uncheck one team', async function () {
MockApiClient.addMockResponse({
method: 'GET',
url: `/organizations/${organization.slug}/key-transactions-list/`,
body: teams.map(({id}) => ({
team: id,
count: 1,
keyed: [{project_id: String(project.id), transaction: 'transaction'}],
})),
});
const deleteTeamKeyTransactionsMock = MockApiClient.addMockResponse({
method: 'DELETE',
url: '/organizations/org-slug/key-transactions/',
body: [],
match: [
MockApiClient.matchQuery({project: [project.id]}),
MockApiClient.matchData({team: [teams[0].id], transaction: 'transaction'}),
],
});
const wrapper = mountWithTheme(
);
await tick();
wrapper.update();
clickTeamKeyTransactionDropdown(wrapper);
expect(
wrapper.find('DropdownMenuItem CheckboxFancy').first().props().isChecked
).toBeTruthy();
wrapper.find('DropdownMenuItem CheckboxFancy').first().simulate('click');
await tick();
wrapper.update();
expect(
wrapper.find('DropdownMenuItem CheckboxFancy').first().props().isChecked
).toBeFalsy();
expect(deleteTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
});
it('should be able to check all with my teams', async function () {
MockApiClient.addMockResponse({
method: 'GET',
url: `/organizations/${organization.slug}/key-transactions-list/`,
body: teams.map(({id}) => ({
team: id,
count: 0,
keyed: [],
})),
});
const postTeamKeyTransactionsMock = MockApiClient.addMockResponse({
method: 'POST',
url: '/organizations/org-slug/key-transactions/',
body: [],
match: [
MockApiClient.matchQuery({project: [project.id]}),
MockApiClient.matchData({
team: [teams[0].id, teams[1].id],
transaction: 'transaction',
}),
],
});
const wrapper = mountWithTheme(
);
await tick();
wrapper.update();
clickTeamKeyTransactionDropdown(wrapper);
wrapper.find('DropdownMenuHeader CheckboxFancy').simulate('click');
await tick();
wrapper.update();
const headerCheckbox = wrapper.find('DropdownMenuHeader CheckboxFancy');
expect(headerCheckbox.props().isChecked).toBeTruthy();
expect(headerCheckbox.props().isIndeterminate).toBeFalsy();
expect(postTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
});
it('should be able to uncheck all with my teams', async function () {
MockApiClient.addMockResponse({
method: 'GET',
url: `/organizations/${organization.slug}/key-transactions-list/`,
body: teams.map(({id}) => ({
team: id,
count: 1,
keyed: [{project_id: String(project.id), transaction: 'transaction'}],
})),
});
const deleteTeamKeyTransactionsMock = MockApiClient.addMockResponse({
method: 'DELETE',
url: '/organizations/org-slug/key-transactions/',
body: [],
match: [
MockApiClient.matchQuery({project: [project.id]}),
MockApiClient.matchData({
team: [teams[0].id, teams[1].id],
transaction: 'transaction',
}),
],
});
const wrapper = mountWithTheme(
);
await tick();
wrapper.update();
clickTeamKeyTransactionDropdown(wrapper);
wrapper.find('DropdownMenuHeader CheckboxFancy').simulate('click');
await tick();
wrapper.update();
const headerCheckbox = wrapper.find('DropdownMenuHeader CheckboxFancy');
expect(headerCheckbox.props().isChecked).toBeFalsy();
expect(headerCheckbox.props().isIndeterminate).toBeFalsy();
expect(deleteTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
});
it('should render teams without access separately', async function () {
const myTeams = [...teams, TestStubs.Team({id: '3', slug: 'team3', name: 'Team 3'})];
act(() => {
TeamStore.loadInitialData(myTeams);
});
MockApiClient.addMockResponse({
method: 'GET',
url: `/organizations/${organization.slug}/key-transactions-list/`,
body: myTeams.map(({id}) => ({
team: id,
count: 0,
keyed: [],
})),
});
const wrapper = mountWithTheme(
);
await tick();
wrapper.update();
clickTeamKeyTransactionDropdown(wrapper);
const headers = wrapper.find('DropdownMenuHeader');
expect(headers.length).toEqual(2);
expect(headers.at(0).text()).toEqual('My Teams with Access');
expect(headers.at(1).text()).toEqual('My Teams without Access');
const entries = wrapper.find('DropdownMenuItem');
expect(entries.length).toEqual(3);
entries.forEach((entry, i) => {
expect(entry.text()).toEqual(myTeams[i].slug);
});
expect(entries.at(0).find('CheckboxFancy').exists()).toBeTruthy();
expect(entries.at(1).find('CheckboxFancy').exists()).toBeTruthy();
// this team does not have access so there is no checkbox
expect(entries.at(2).find('CheckboxFancy').exists()).toBeFalsy();
});
});