import { render, screen, fireEvent, waitForElementToBeRemoved, } from '@testing-library/react' import { expect } from 'chai' import { UserEmailData } from '../../../../../../types/user-email' import fetchMock from 'fetch-mock' import InstitutionAndRole from '../../../../../../frontend/js/features/settings/components/emails/institution-and-role' import { UserEmailsProvider } from '../../../../../../frontend/js/features/settings/context/user-email-context' import EmailsSection from '../../../../../../frontend/js/features/settings/components/emails-section' import { Affiliation } from '../../../../../../types/affiliation' const userData1: UserEmailData & { affiliation: Affiliation } = { affiliation: { cachedConfirmedAt: null, cachedEntitlement: null, cachedLastDayToReconfirm: null, cachedPastReconfirmDate: false, cachedReconfirmedAt: null, department: null, institution: { commonsAccount: false, confirmed: true, id: 1, isUniversity: false, maxConfirmationMonths: null, name: 'Overleaf', ssoEnabled: false, ssoBeta: false, }, inReconfirmNotificationPeriod: false, inferred: false, licence: 'pro_plus', pastReconfirmDate: false, portal: { slug: '', templates_count: 1 }, role: null, }, confirmedAt: '2022-03-09T10:59:44.139Z', email: 'foo@overleaf.com', default: true, } const userData2: UserEmailData & { affiliation: Affiliation } = { affiliation: { cachedConfirmedAt: null, cachedEntitlement: null, cachedLastDayToReconfirm: null, cachedPastReconfirmDate: false, cachedReconfirmedAt: null, department: 'Art History', institution: { commonsAccount: false, confirmed: true, id: 1, isUniversity: false, maxConfirmationMonths: null, name: 'Overleaf', ssoEnabled: false, ssoBeta: false, }, inReconfirmNotificationPeriod: false, inferred: false, licence: 'pro_plus', pastReconfirmDate: false, portal: { slug: '', templates_count: 1 }, role: 'Reader', }, email: 'baz@overleaf.com', default: false, } describe('user role and institution', function () { beforeEach(function () { window.metaAttributesCache = new Map() window.metaAttributesCache.set('ol-ExposedSettings', { hasAffiliationsFeature: true, }) fetchMock.reset() fetchMock.get('/user/emails?ensureAffiliation=true', []) }) afterEach(function () { window.metaAttributesCache = new Map() fetchMock.reset() }) it('renders affiliation name with add role/department button', function () { const userEmailData = userData1 render( ) screen.getByText(userEmailData.affiliation.institution.name, { exact: false, }) screen.getByRole('button', { name: /add role and department/i }) expect(screen.queryByRole('button', { name: /change/i })).to.not.exist }) it('renders affiliation name, role and department with change button', function () { const userEmailData = userData2 render( ) screen.getByText(userEmailData.affiliation.institution.name, { exact: false, }) screen.getByText(userEmailData.affiliation.department!, { exact: false }) screen.getByText(userEmailData.affiliation.role!, { exact: false }) screen.getByRole('button', { name: /change/i }) expect(screen.queryByRole('button', { name: /add role and department/i })) .to.not.exist }) it('fetches institution data and replaces departments dropdown on add/change', async function () { const userEmailData = userData1 fetchMock.get('/user/emails?ensureAffiliation=true', [userEmailData], { overwriteRoutes: true, }) render() await fetchMock.flush(true) fetchMock.reset() const fakeDepartment = 'Fake department' const institution = userEmailData.affiliation.institution fetchMock.get(`/institutions/list/${institution.id}`, { id: institution.id, name: institution.name, country_code: 'de', departments: [fakeDepartment], }) fireEvent.click( screen.getByRole('button', { name: /add role and department/i }) ) await fetchMock.flush(true) fetchMock.reset() fireEvent.click(screen.getByRole('textbox', { name: /department/i })) screen.getByText(fakeDepartment) }) it('adds new role and department', async function () { fetchMock .get('/user/emails?ensureAffiliation=true', [userData1], { overwriteRoutes: true, }) .get(/\/institutions\/list/, { departments: [] }) .post('/user/emails/endorse', 200) render() const addBtn = await screen.findByRole('button', { name: /add role and department/i, }) fireEvent.click(addBtn) const submitBtn = screen.getByRole('button', { name: /save/i, }) as HTMLButtonElement expect(submitBtn.disabled).to.be.true const roleValue = 'Dummy role' const departmentValue = 'Dummy department' const roleInput = screen.getByPlaceholderText(/role/i) fireEvent.change(roleInput, { target: { value: roleValue }, }) expect(submitBtn.disabled).to.be.true const departmentInput = screen.getByPlaceholderText(/department/i) fireEvent.change(departmentInput, { target: { value: departmentValue }, }) expect(submitBtn.disabled).to.be.false fireEvent.click(submitBtn) expect(submitBtn.disabled).to.be.true await waitForElementToBeRemoved(() => screen.getByRole('button', { name: /saving/i }) ) screen.getByText(roleValue, { exact: false }) screen.getByText(departmentValue, { exact: false }) }) })