import {OrganizationFixture} from 'sentry-fixture/organization';
import {RouteComponentPropsFixture} from 'sentry-fixture/routeComponentPropsFixture';
import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
import {logout} from 'sentry/actionCreators/account';
import ConfigStore from 'sentry/stores/configStore';
import {browserHistory} from 'sentry/utils/browserHistory';
import AcceptOrganizationInvite from 'sentry/views/acceptOrganizationInvite';
jest.mock('sentry/actionCreators/account');
const addMock = body =>
MockApiClient.addMockResponse({
url: '/accept-invite/org-slug/1/abc/',
method: 'GET',
body,
});
const getJoinButton = () => {
const maybeButton = screen.queryByRole('button', {
name: 'Join the org-slug organization',
});
return maybeButton;
};
describe('AcceptOrganizationInvite', function () {
const organization = OrganizationFixture({slug: 'org-slug'});
const configState = ConfigStore.getState();
afterEach(() => {
ConfigStore.loadInitialData(configState);
});
it('can accept invitation', async function () {
addMock({
orgSlug: organization.slug,
needsAuthentication: false,
needs2fa: false,
hasAuthProvider: false,
requireSso: false,
existingMember: false,
});
render(
);
const acceptMock = MockApiClient.addMockResponse({
url: '/accept-invite/org-slug/1/abc/',
method: 'POST',
});
const joinButton = getJoinButton();
await userEvent.click(joinButton!);
expect(acceptMock).toHaveBeenCalled();
expect(browserHistory.replace).toHaveBeenCalledWith('/org-slug/');
});
it('can accept invitation on customer-domains', async function () {
ConfigStore.set('customerDomain', {
subdomain: 'org-slug',
organizationUrl: 'https://org-slug.sentry.io',
sentryUrl: 'https://sentry.io',
});
ConfigStore.set('links', {
...configState.links,
sentryUrl: 'https://sentry.io',
});
addMock({
orgSlug: organization.slug,
needsAuthentication: false,
needs2fa: false,
hasAuthProvider: false,
requireSso: false,
existingMember: false,
});
render(
);
const acceptMock = MockApiClient.addMockResponse({
url: '/accept-invite/org-slug/1/abc/',
method: 'POST',
});
const joinButton = getJoinButton();
await userEvent.click(joinButton!);
expect(acceptMock).toHaveBeenCalled();
expect(browserHistory.replace).toHaveBeenCalledWith('/org-slug/');
});
it('renders error message', function () {
MockApiClient.addMockResponse({
url: '/accept-invite/1/abc/',
method: 'GET',
statusCode: 400,
body: {detail: 'uh oh'},
});
render(
);
expect(getJoinButton()).not.toBeInTheDocument();
expect(
screen.getByRole('link', {name: 'sign in with a different account'})
).toBeInTheDocument();
});
it('requires authentication to join', function () {
addMock({
orgSlug: organization.slug,
needsAuthentication: true,
needs2fa: false,
hasAuthProvider: false,
requireSso: false,
existingMember: false,
});
render(
);
expect(getJoinButton()).not.toBeInTheDocument();
expect(screen.getByTestId('action-info-general')).toBeInTheDocument();
expect(screen.queryByTestId('action-info-sso')).not.toBeInTheDocument();
expect(
screen.getByRole('button', {name: 'Create a new account'})
).toBeInTheDocument();
expect(
screen.getByRole('link', {name: 'Login using an existing account'})
).toBeInTheDocument();
});
it('suggests sso authentication to login', function () {
addMock({
orgSlug: organization.slug,
needsAuthentication: true,
needs2fa: false,
hasAuthProvider: true,
requireSso: false,
existingMember: false,
ssoProvider: 'SSO',
});
render(
);
expect(getJoinButton()).not.toBeInTheDocument();
expect(screen.getByTestId('action-info-general')).toBeInTheDocument();
expect(screen.getByTestId('action-info-sso')).toBeInTheDocument();
expect(screen.getByRole('button', {name: 'Join with SSO'})).toBeInTheDocument();
expect(
screen.getByRole('button', {name: 'Create a new account'})
).toBeInTheDocument();
expect(
screen.getByRole('link', {name: 'Login using an existing account'})
).toBeInTheDocument();
});
it('enforce required sso authentication', function () {
addMock({
orgSlug: organization.slug,
needsAuthentication: true,
needs2fa: false,
hasAuthProvider: true,
requireSso: true,
existingMember: false,
ssoProvider: 'SSO',
});
render(
);
expect(getJoinButton()).not.toBeInTheDocument();
expect(screen.queryByTestId('action-info-general')).not.toBeInTheDocument();
expect(screen.getByTestId('action-info-sso')).toBeInTheDocument();
expect(screen.getByRole('button', {name: 'Join with SSO'})).toBeInTheDocument();
expect(
screen.queryByRole('button', {name: 'Create a new account'})
).not.toBeInTheDocument();
expect(
screen.queryByRole('link', {name: 'Login using an existing account'})
).not.toBeInTheDocument();
});
it('enforce required sso authentication for logged in users', function () {
addMock({
orgSlug: organization.slug,
needsAuthentication: false,
needs2fa: false,
hasAuthProvider: true,
requireSso: true,
existingMember: false,
ssoProvider: 'SSO',
});
render(
);
expect(getJoinButton()).not.toBeInTheDocument();
expect(screen.queryByTestId('action-info-general')).not.toBeInTheDocument();
expect(screen.getByTestId('action-info-sso')).toBeInTheDocument();
expect(screen.getByRole('button', {name: 'Join with SSO'})).toBeInTheDocument();
expect(
screen.queryByRole('button', {name: 'Create a new account'})
).not.toBeInTheDocument();
expect(
screen.queryByRole('link', {name: 'Login using an existing account'})
).not.toBeInTheDocument();
});
it('show logout button for logged in users w/ sso and membership', async function () {
addMock({
orgSlug: organization.slug,
needsAuthentication: false,
needs2fa: false,
hasAuthProvider: true,
requireSso: true,
existingMember: true,
ssoProvider: 'SSO',
});
render(
);
expect(screen.getByTestId('existing-member')).toBeInTheDocument();
await userEvent.click(screen.getByTestId('existing-member-link'));
await waitFor(() => expect(logout).toHaveBeenCalled());
});
it('shows right options for logged in user and optional SSO', function () {
addMock({
orgSlug: organization.slug,
needsAuthentication: false,
needs2fa: false,
hasAuthProvider: true,
requireSso: false,
existingMember: false,
ssoProvider: 'SSO',
});
render(
);
expect(screen.getByTestId('action-info-sso')).toBeInTheDocument();
expect(getJoinButton()).toBeInTheDocument();
});
it('shows a logout button for existing members', async function () {
addMock({
orgSlug: organization.slug,
needsAuthentication: false,
needs2fa: false,
hasAuthProvider: false,
requireSso: false,
existingMember: true,
});
render(
);
expect(screen.getByTestId('existing-member')).toBeInTheDocument();
await userEvent.click(screen.getByTestId('existing-member-link'));
await waitFor(() => expect(logout).toHaveBeenCalled());
});
it('shows 2fa warning', function () {
addMock({
orgSlug: organization.slug,
needsAuthentication: false,
needs2fa: true,
hasAuthProvider: false,
requireSso: false,
existingMember: false,
});
render(
);
expect(
screen.getByRole('button', {name: 'Configure Two-Factor Auth'})
).toBeInTheDocument();
});
});