mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 14:43:46 +01:00
Merge pull request #23940 from overleaf/td-react-18
Upgrade to React 18 GitOrigin-RevId: 9b81936e6eea2bccd97fe5c2c5841f0b946371b8
This commit is contained in:
+6
-12
@@ -3,23 +3,16 @@ import { expect } from 'chai'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import sinon from 'sinon'
|
||||
import ModalContentNewProjectForm from '../../../../../../frontend/js/features/project-list/components/new-project-button/modal-content-new-project-form'
|
||||
import * as useLocationModule from '../../../../../../frontend/js/shared/hooks/use-location'
|
||||
import { location } from '@/shared/components/location'
|
||||
|
||||
describe('<ModalContentNewProjectForm />', function () {
|
||||
let assignStub: sinon.SinonStub
|
||||
|
||||
beforeEach(function () {
|
||||
assignStub = sinon.stub()
|
||||
this.locationStub = sinon.stub(useLocationModule, 'useLocation').returns({
|
||||
assign: assignStub,
|
||||
replace: sinon.stub(),
|
||||
reload: sinon.stub(),
|
||||
setHash: sinon.stub(),
|
||||
})
|
||||
this.locationWrapperSandbox = sinon.createSandbox()
|
||||
this.locationWrapperStub = this.locationWrapperSandbox.stub(location)
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
this.locationStub.restore()
|
||||
this.locationWrapperSandbox.restore()
|
||||
fetchMock.removeRoutes().clearHistory()
|
||||
})
|
||||
|
||||
@@ -51,10 +44,11 @@ describe('<ModalContentNewProjectForm />', function () {
|
||||
|
||||
expect(newProjectMock.callHistory.called()).to.be.true
|
||||
|
||||
const assignStub = this.locationWrapperStub.assign
|
||||
await waitFor(() => {
|
||||
sinon.assert.calledOnce(assignStub)
|
||||
sinon.assert.calledWith(assignStub, `/project/${projectId}`)
|
||||
})
|
||||
sinon.assert.calledWith(assignStub, `/project/${projectId}`)
|
||||
})
|
||||
|
||||
it('shows error when project name contains "/"', async function () {
|
||||
|
||||
+23
-28
@@ -41,7 +41,7 @@ import { Project } from '../../../../../types/project/dashboard/api'
|
||||
import GroupsAndEnterpriseBanner from '../../../../../frontend/js/features/project-list/components/notifications/groups-and-enterprise-banner'
|
||||
import GroupSsoSetupSuccess from '../../../../../frontend/js/features/project-list/components/notifications/groups/group-sso-setup-success'
|
||||
import localStorage from '@/infrastructure/local-storage'
|
||||
import * as useLocationModule from '../../../../../frontend/js/shared/hooks/use-location'
|
||||
import { location } from '@/shared/components/location'
|
||||
import {
|
||||
commonsSubscription,
|
||||
freeSubscription,
|
||||
@@ -50,7 +50,9 @@ import {
|
||||
} from '../fixtures/user-subscriptions'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
const renderWithinProjectListProvider = (Component: React.ComponentType) => {
|
||||
const renderWithinProjectListProvider = (
|
||||
Component: React.ComponentType<React.PropsWithChildren>
|
||||
) => {
|
||||
render(<Component />, {
|
||||
wrapper: ({ children }) => (
|
||||
<ProjectListProvider>
|
||||
@@ -655,12 +657,10 @@ describe('<UserNotifications />', function () {
|
||||
window.metaAttributesCache.set('ol-user', {
|
||||
signUpDate: new Date('2024-01-01').toISOString(),
|
||||
})
|
||||
this.clock = sinon.useFakeTimers(new Date('2025-07-01').getTime())
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
fetchMock.removeRoutes().clearHistory()
|
||||
this.clock.restore()
|
||||
})
|
||||
|
||||
function testUnconfirmedNotification(
|
||||
@@ -675,7 +675,9 @@ describe('<UserNotifications />', function () {
|
||||
fetchMock.post('/user/emails/resend_confirmation', 200)
|
||||
|
||||
const email = userEmails[0].email
|
||||
const notificationBody = screen.getByTestId('pro-notification-body')
|
||||
const notificationBody = await screen.findByTestId(
|
||||
'pro-notification-body'
|
||||
)
|
||||
|
||||
if (isPrimary) {
|
||||
expect(notificationBody.textContent).to.contain(
|
||||
@@ -691,7 +693,7 @@ describe('<UserNotifications />', function () {
|
||||
fireEvent.click(resendButton)
|
||||
|
||||
await waitForElementToBeRemoved(() =>
|
||||
screen.getByRole('button', { name: /resend/i })
|
||||
screen.queryByRole('button', { name: /resend/i })
|
||||
)
|
||||
|
||||
expect(fetchMock.callHistory.called()).to.be.true
|
||||
@@ -717,7 +719,7 @@ describe('<UserNotifications />', function () {
|
||||
fetchMock.post('/user/emails/resend_confirmation', 200)
|
||||
|
||||
const email = untrustedUserData.email
|
||||
const notificationBody = screen.getByTestId(
|
||||
const notificationBody = await screen.findByTestId(
|
||||
'not-trusted-notification-body'
|
||||
)
|
||||
expect(notificationBody.textContent).to.contain(
|
||||
@@ -742,7 +744,9 @@ describe('<UserNotifications />', function () {
|
||||
await fetchMock.callHistory.flush(true)
|
||||
fetchMock.post('/user/emails/resend_confirmation', 500)
|
||||
|
||||
const resendButtons = screen.getAllByRole('button', { name: /resend/i })
|
||||
const resendButtons = await screen.findAllByRole('button', {
|
||||
name: /resend/i,
|
||||
})
|
||||
const resendButton = resendButtons[0]
|
||||
fireEvent.click(resendButton)
|
||||
const notificationBody = screen.getByTestId('pro-notification-body')
|
||||
@@ -767,7 +771,7 @@ describe('<UserNotifications />', function () {
|
||||
renderWithinProjectListProvider(ConfirmEmail)
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
const alert = screen.getByRole('alert')
|
||||
const alert = await screen.findByRole('alert')
|
||||
const email = unconfirmedCommonsUserData.email
|
||||
const notificationBody = within(alert).getByTestId('notification-body')
|
||||
expect(notificationBody.textContent).to.contain(
|
||||
@@ -788,7 +792,7 @@ describe('<UserNotifications />', function () {
|
||||
renderWithinProjectListProvider(ConfirmEmail)
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
const alert = screen.getByRole('alert')
|
||||
const alert = await screen.findByRole('alert')
|
||||
const email = unconfirmedCommonsUserData.email
|
||||
const notificationBody = within(alert).getByTestId(
|
||||
'pro-notification-body'
|
||||
@@ -808,22 +812,15 @@ describe('<UserNotifications />', function () {
|
||||
})
|
||||
|
||||
describe('<Affiliation/>', function () {
|
||||
let assignStub: sinon.SinonStub
|
||||
|
||||
beforeEach(function () {
|
||||
Object.assign(getMeta('ol-ExposedSettings'), exposedSettings)
|
||||
assignStub = sinon.stub()
|
||||
this.locationStub = sinon.stub(useLocationModule, 'useLocation').returns({
|
||||
assign: assignStub,
|
||||
replace: sinon.stub(),
|
||||
reload: sinon.stub(),
|
||||
setHash: sinon.stub(),
|
||||
})
|
||||
this.locationWrapperSandbox = sinon.createSandbox()
|
||||
this.locationWrapperStub = this.locationWrapperSandbox.stub(location)
|
||||
fetchMock.removeRoutes().clearHistory()
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
this.locationStub.restore()
|
||||
this.locationWrapperSandbox.restore()
|
||||
fetchMock.removeRoutes().clearHistory()
|
||||
})
|
||||
|
||||
@@ -879,9 +876,9 @@ describe('<UserNotifications />', function () {
|
||||
fireEvent.click(
|
||||
screen.getByRole('button', { name: /confirm affiliation/i })
|
||||
)
|
||||
sinon.assert.calledOnce(assignStub)
|
||||
sinon.assert.calledOnce(this.locationWrapperStub.assign)
|
||||
sinon.assert.calledWithMatch(
|
||||
assignStub,
|
||||
this.locationWrapperStub.assign,
|
||||
`${exposedSettings.samlInitPath}?university_id=${professionalUserData.affiliation.institution.id}&reconfirm=/project`
|
||||
)
|
||||
})
|
||||
@@ -944,8 +941,7 @@ describe('<UserNotifications />', function () {
|
||||
renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
expect(screen.queryByRole('button', { name: 'Contact Sales' })).to.not.be
|
||||
.null
|
||||
await screen.findByRole('button', { name: 'Contact Sales' })
|
||||
})
|
||||
|
||||
it('shows the banner for users that have dismissed the banner more than 30 days ago', async function () {
|
||||
@@ -960,8 +956,7 @@ describe('<UserNotifications />', function () {
|
||||
renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
expect(screen.queryByRole('button', { name: 'Contact Sales' })).to.not.be
|
||||
.null
|
||||
await screen.findByRole('button', { name: 'Contact Sales' })
|
||||
})
|
||||
|
||||
it('does not show the banner for users that have dismissed the banner within the last 30 days', async function () {
|
||||
@@ -1014,7 +1009,7 @@ describe('<UserNotifications />', function () {
|
||||
renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
screen.getByText(
|
||||
await screen.findByText(
|
||||
'Overleaf On-Premises: Does your company want to keep its data within its firewall? Overleaf offers Server Pro, an on-premises solution for companies. Get in touch to learn more.'
|
||||
)
|
||||
const link = screen.getByRole('button', { name: 'Contact Sales' })
|
||||
@@ -1031,7 +1026,7 @@ describe('<UserNotifications />', function () {
|
||||
renderWithinProjectListProvider(GroupsAndEnterpriseBanner)
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
screen.getByText(
|
||||
await screen.findByText(
|
||||
'Why do Fortune 500 companies and top research institutions trust Overleaf to streamline their collaboration? Get in touch to learn more.'
|
||||
)
|
||||
const link = screen.getByRole('button', { name: 'Contact Sales' })
|
||||
|
||||
+42
-31
@@ -19,7 +19,7 @@ import {
|
||||
archiveableProject,
|
||||
copyableProject,
|
||||
} from '../fixtures/projects-data'
|
||||
import * as useLocationModule from '../../../../../frontend/js/shared/hooks/use-location'
|
||||
import { location } from '@/shared/components/location'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
const {
|
||||
@@ -37,7 +37,6 @@ describe('<ProjectListRoot />', function () {
|
||||
this.timeout('10s')
|
||||
|
||||
let sendMBSpy: sinon.SinonSpy
|
||||
let assignStub: sinon.SinonStub
|
||||
|
||||
beforeEach(async function () {
|
||||
global.localStorage.clear()
|
||||
@@ -68,19 +67,14 @@ describe('<ProjectListRoot />', function () {
|
||||
window.metaAttributesCache.set('ol-navbar', {
|
||||
items: [],
|
||||
})
|
||||
assignStub = sinon.stub()
|
||||
this.locationStub = sinon.stub(useLocationModule, 'useLocation').returns({
|
||||
assign: assignStub,
|
||||
replace: sinon.stub(),
|
||||
reload: sinon.stub(),
|
||||
setHash: sinon.stub(),
|
||||
})
|
||||
this.locationWrapperSandbox = sinon.createSandbox()
|
||||
this.locationWrapperStub = this.locationWrapperSandbox.stub(location)
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
sendMBSpy.restore()
|
||||
fetchMock.removeRoutes().clearHistory()
|
||||
this.locationStub.restore()
|
||||
this.locationWrapperSandbox.restore()
|
||||
})
|
||||
|
||||
describe('welcome page', function () {
|
||||
@@ -136,6 +130,7 @@ describe('<ProjectListRoot />', function () {
|
||||
within(actionsToolbar).getByLabelText('Download')
|
||||
fireEvent.click(downloadButton)
|
||||
|
||||
const assignStub = this.locationWrapperStub.assign
|
||||
await waitFor(() => {
|
||||
expect(assignStub).to.have.been.called
|
||||
})
|
||||
@@ -430,12 +425,15 @@ describe('<ProjectListRoot />', function () {
|
||||
{ repeat: leavableList.length }
|
||||
)
|
||||
|
||||
allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
// + 1 because of select all
|
||||
expect(allCheckboxes.length).to.equal(leavableList.length + 1)
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
screen.getAllByRole<HTMLInputElement>('checkbox').length
|
||||
).to.equal(leavableList.length + 1)
|
||||
)
|
||||
|
||||
// first one is the select all checkbox
|
||||
fireEvent.click(allCheckboxes[0])
|
||||
fireEvent.click(screen.getAllByRole('checkbox')[0])
|
||||
|
||||
actionsToolbar = screen.getAllByRole('toolbar')[0]
|
||||
|
||||
@@ -491,9 +489,11 @@ describe('<ProjectListRoot />', function () {
|
||||
{ repeat: deletableList.length }
|
||||
)
|
||||
|
||||
allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
// + 1 because of select all
|
||||
expect(allCheckboxes.length).to.equal(deletableList.length + 1)
|
||||
await waitFor(() => {
|
||||
allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
// + 1 because of select all
|
||||
expect(allCheckboxes.length).to.equal(deletableList.length + 1)
|
||||
})
|
||||
|
||||
// first one is the select all checkbox
|
||||
fireEvent.click(allCheckboxes[0])
|
||||
@@ -563,14 +563,15 @@ describe('<ProjectListRoot />', function () {
|
||||
{ repeat: leavableList.length }
|
||||
)
|
||||
|
||||
allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
// + 1 because of select all
|
||||
expect(allCheckboxes.length).to.equal(
|
||||
deletableAndLeavableList.length + 1
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
screen.getAllByRole<HTMLInputElement>('checkbox').length
|
||||
).to.equal(deletableAndLeavableList.length + 1)
|
||||
)
|
||||
|
||||
// first one is the select all checkbox
|
||||
fireEvent.click(allCheckboxes[0])
|
||||
fireEvent.click(screen.getAllByRole<HTMLInputElement>('checkbox')[0])
|
||||
|
||||
actionsToolbar = screen.getAllByRole('toolbar')[0]
|
||||
|
||||
@@ -663,9 +664,11 @@ describe('<ProjectListRoot />', function () {
|
||||
)
|
||||
).to.be.true
|
||||
})
|
||||
expect(
|
||||
screen.queryAllByText(projectsData[index].name)
|
||||
).to.have.length(0)
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.queryAllByText(projectsData[index].name)
|
||||
).to.have.length(0)
|
||||
})
|
||||
|
||||
screen.getAllByRole('button', {
|
||||
name: `${this.tagName} (${--visibleProjectsCount})`,
|
||||
@@ -699,13 +702,15 @@ describe('<ProjectListRoot />', function () {
|
||||
status: 204,
|
||||
})
|
||||
|
||||
await waitFor(() => {
|
||||
const tagsDropdown = within(actionsToolbar).getByLabelText('Tags')
|
||||
fireEvent.click(tagsDropdown)
|
||||
})
|
||||
const tagsDropdown =
|
||||
await within(actionsToolbar).findByLabelText('Tags')
|
||||
fireEvent.click(tagsDropdown)
|
||||
screen.getByText('Add to tag')
|
||||
|
||||
const newTagButton = screen.getByText('Create new tag')
|
||||
const newTagButton = screen.getByRole('menuitem', {
|
||||
name: 'Create new tag',
|
||||
})
|
||||
|
||||
fireEvent.click(newTagButton)
|
||||
|
||||
const modal = screen.getAllByRole('dialog')[0]
|
||||
@@ -731,7 +736,11 @@ describe('<ProjectListRoot />', function () {
|
||||
})
|
||||
).to.be.true
|
||||
|
||||
screen.getByRole('button', { name: `${this.newTagName} (2)` })
|
||||
await screen.findByRole(
|
||||
'button',
|
||||
{ name: `${this.newTagName} (2)` },
|
||||
{ timeout: 5000 }
|
||||
)
|
||||
})
|
||||
|
||||
it('opens the tags dropdown and remove a tag from selected projects', async function () {
|
||||
@@ -949,7 +958,7 @@ describe('<ProjectListRoot />', function () {
|
||||
).to.be.true
|
||||
|
||||
const table = await screen.findByRole('table')
|
||||
within(table).getByText(newProjectName)
|
||||
await within(table).findByText(newProjectName)
|
||||
expect(within(table).queryByText(oldName)).to.be.null
|
||||
|
||||
const allCheckboxesInTable =
|
||||
@@ -1025,7 +1034,7 @@ describe('<ProjectListRoot />', function () {
|
||||
}
|
||||
)
|
||||
|
||||
screen.getByText(copiedProjectName)
|
||||
await screen.findByText(copiedProjectName)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1073,6 +1082,8 @@ describe('<ProjectListRoot />', function () {
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
fetchMock.removeRoutes().clearHistory()
|
||||
|
||||
allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
// first one is the select all checkbox, just check 2 at first
|
||||
fireEvent.click(allCheckboxes[1])
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ describe('Add affiliation widget', function () {
|
||||
await fetchMock.callHistory.flush(true)
|
||||
await waitFor(() => expect(fetchMock.callHistory.called('/api/project')))
|
||||
|
||||
screen.getByText(/are you affiliated with an institution/i)
|
||||
await screen.findByText(/are you affiliated with an institution/i)
|
||||
const addAffiliationLink = screen.getByRole('button', {
|
||||
name: /add affiliation/i,
|
||||
})
|
||||
|
||||
+23
-17
@@ -63,7 +63,7 @@ describe('<TagsList />', function () {
|
||||
const tag1Button = screen.getByText('Tag 1')
|
||||
assert.isFalse(tag1Button.closest('li')?.classList.contains('active'))
|
||||
|
||||
await fireEvent.click(tag1Button)
|
||||
fireEvent.click(tag1Button)
|
||||
assert.isTrue(tag1Button.closest('li')?.classList.contains('active'))
|
||||
})
|
||||
|
||||
@@ -85,7 +85,7 @@ describe('<TagsList />', function () {
|
||||
name: 'New Tag',
|
||||
})
|
||||
|
||||
await fireEvent.click(newTagButton)
|
||||
fireEvent.click(newTagButton)
|
||||
})
|
||||
|
||||
it('modal is open', async function () {
|
||||
@@ -97,7 +97,7 @@ describe('<TagsList />', function () {
|
||||
const modal = screen.getAllByRole('dialog', { hidden: false })[0]
|
||||
const cancelButton = within(modal).getByRole('button', { name: 'Cancel' })
|
||||
|
||||
await fireEvent.click(cancelButton)
|
||||
fireEvent.click(cancelButton)
|
||||
expect(screen.queryByRole('dialog', { hidden: false })).to.be.null
|
||||
})
|
||||
|
||||
@@ -144,13 +144,15 @@ describe('<TagsList />', function () {
|
||||
const createButton = within(modal).getByRole('button', { name: 'Create' })
|
||||
expect(createButton.hasAttribute('disabled')).to.be.false
|
||||
|
||||
await fireEvent.click(createButton)
|
||||
fireEvent.click(createButton)
|
||||
|
||||
await waitFor(
|
||||
() => expect(fetchMock.callHistory.called(`/tag`)).to.be.true
|
||||
)
|
||||
|
||||
expect(screen.queryByRole('dialog', { hidden: false })).to.be.null
|
||||
await waitFor(
|
||||
() => expect(screen.queryByRole('dialog', { hidden: false })).to.be.null
|
||||
)
|
||||
|
||||
screen.getByRole('button', {
|
||||
name: 'New Tag (0)',
|
||||
@@ -164,9 +166,9 @@ describe('<TagsList />', function () {
|
||||
const dropdownToggle = within(
|
||||
tag1Button.closest('li') as HTMLElement
|
||||
).getByTestId('tag-dropdown-toggle')
|
||||
await fireEvent.click(dropdownToggle)
|
||||
fireEvent.click(dropdownToggle)
|
||||
const editMenuItem = await screen.findByRole('menuitem', { name: 'Edit' })
|
||||
await fireEvent.click(editMenuItem)
|
||||
fireEvent.click(editMenuItem)
|
||||
})
|
||||
|
||||
it('modal is open', async function () {
|
||||
@@ -178,7 +180,7 @@ describe('<TagsList />', function () {
|
||||
const modal = screen.getAllByRole('dialog', { hidden: false })[0]
|
||||
const cancelButton = within(modal).getByRole('button', { name: 'Cancel' })
|
||||
|
||||
await fireEvent.click(cancelButton)
|
||||
fireEvent.click(cancelButton)
|
||||
expect(screen.queryByRole('dialog', { hidden: false })).to.be.null
|
||||
})
|
||||
|
||||
@@ -237,13 +239,15 @@ describe('<TagsList />', function () {
|
||||
const saveButton = within(modal).getByRole('button', { name: 'Save' })
|
||||
expect(saveButton.hasAttribute('disabled')).to.be.false
|
||||
|
||||
await fireEvent.click(saveButton)
|
||||
fireEvent.click(saveButton)
|
||||
|
||||
await waitFor(() =>
|
||||
expect(fetchMock.callHistory.called(`/tag/abc123def456/rename`))
|
||||
)
|
||||
|
||||
expect(screen.queryByRole('dialog', { hidden: false })).to.be.null
|
||||
await waitFor(
|
||||
() => expect(screen.queryByRole('dialog', { hidden: false })).to.be.null
|
||||
)
|
||||
|
||||
screen.getByRole('button', {
|
||||
name: 'New Tag Name (1)',
|
||||
@@ -257,11 +261,11 @@ describe('<TagsList />', function () {
|
||||
const dropdownToggle = within(
|
||||
tag1Button.closest('li') as HTMLElement
|
||||
).getByTestId('tag-dropdown-toggle')
|
||||
await fireEvent.click(dropdownToggle)
|
||||
fireEvent.click(dropdownToggle)
|
||||
const deleteMenuItem = await screen.findByRole('menuitem', {
|
||||
name: 'Delete',
|
||||
})
|
||||
await fireEvent.click(deleteMenuItem)
|
||||
fireEvent.click(deleteMenuItem)
|
||||
})
|
||||
|
||||
it('modal is open', async function () {
|
||||
@@ -273,20 +277,22 @@ describe('<TagsList />', function () {
|
||||
const modal = screen.getAllByRole('dialog', { hidden: false })[0]
|
||||
const cancelButton = within(modal).getByRole('button', { name: 'Cancel' })
|
||||
|
||||
await fireEvent.click(cancelButton)
|
||||
fireEvent.click(cancelButton)
|
||||
expect(screen.queryByRole('dialog', { hidden: false })).to.be.null
|
||||
})
|
||||
|
||||
it('clicking Delete sends a request', async function () {
|
||||
const modal = screen.getAllByRole('dialog', { hidden: false })[0]
|
||||
const deleteButton = within(modal).getByRole('button', { name: 'Delete' })
|
||||
await fireEvent.click(deleteButton)
|
||||
fireEvent.click(deleteButton)
|
||||
|
||||
await waitFor(() =>
|
||||
expect(fetchMock.callHistory.called(`/tag/bcd234efg567`))
|
||||
)
|
||||
|
||||
expect(screen.queryByRole('dialog', { hidden: false })).to.be.null
|
||||
await waitFor(
|
||||
() => expect(screen.queryByRole('dialog', { hidden: false })).to.be.null
|
||||
)
|
||||
expect(
|
||||
screen.queryByRole('button', {
|
||||
name: 'Another Tag (2)',
|
||||
@@ -299,13 +305,13 @@ describe('<TagsList />', function () {
|
||||
|
||||
const modal = screen.getAllByRole('dialog', { hidden: false })[0]
|
||||
const deleteButton = within(modal).getByRole('button', { name: 'Delete' })
|
||||
await fireEvent.click(deleteButton)
|
||||
fireEvent.click(deleteButton)
|
||||
|
||||
await waitFor(() =>
|
||||
expect(fetchMock.callHistory.called(`/tag/bcd234efg567`))
|
||||
)
|
||||
|
||||
within(modal).getByText('Sorry, something went wrong')
|
||||
await within(modal).findByText('Sorry, something went wrong')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@ describe('<SystemMessages />', function () {
|
||||
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
screen.getByText(data.content)
|
||||
await screen.findByText(data.content)
|
||||
expect(screen.queryByRole('button', { name: /close/i })).to.be.null
|
||||
})
|
||||
|
||||
@@ -38,7 +38,7 @@ describe('<SystemMessages />', function () {
|
||||
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
screen.getByText(data.content)
|
||||
await screen.findByText(data.content)
|
||||
const closeBtn = screen.getByRole('button', { name: /close/i })
|
||||
fireEvent.click(closeBtn)
|
||||
|
||||
|
||||
+9
-15
@@ -2,32 +2,25 @@ import { expect } from 'chai'
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import sinon from 'sinon'
|
||||
import { projectsData } from '../../../../fixtures/projects-data'
|
||||
import * as useLocationModule from '../../../../../../../../frontend/js/shared/hooks/use-location'
|
||||
import { location } from '@/shared/components/location'
|
||||
import { CompileAndDownloadProjectPDFButtonTooltip } from '../../../../../../../../frontend/js/features/project-list/components/table/cells/action-buttons/compile-and-download-project-pdf-button'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import * as eventTracking from '@/infrastructure/event-tracking'
|
||||
|
||||
describe('<CompileAndDownloadProjectPDFButton />', function () {
|
||||
let assignStub: sinon.SinonStub
|
||||
let locationStub: sinon.SinonStub
|
||||
let sendMBSpy: sinon.SinonSpy
|
||||
|
||||
beforeEach(function () {
|
||||
sendMBSpy = sinon.spy(eventTracking, 'sendMB')
|
||||
assignStub = sinon.stub()
|
||||
locationStub = sinon.stub(useLocationModule, 'useLocation').returns({
|
||||
assign: assignStub,
|
||||
replace: sinon.stub(),
|
||||
reload: sinon.stub(),
|
||||
setHash: sinon.stub(),
|
||||
})
|
||||
this.locationWrapperSandbox = sinon.createSandbox()
|
||||
this.locationWrapperStub = this.locationWrapperSandbox.stub(location)
|
||||
render(
|
||||
<CompileAndDownloadProjectPDFButtonTooltip project={projectsData[0]} />
|
||||
)
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
locationStub.restore()
|
||||
this.locationWrapperSandbox.restore()
|
||||
fetchMock.removeRoutes().clearHistory()
|
||||
sendMBSpy.restore()
|
||||
})
|
||||
@@ -57,6 +50,7 @@ describe('<CompileAndDownloadProjectPDFButton />', function () {
|
||||
screen.getByRole('button', { name: 'Compiling…' })
|
||||
})
|
||||
|
||||
const assignStub = this.locationWrapperStub.assign
|
||||
await waitFor(() => {
|
||||
expect(assignStub).to.have.been.called
|
||||
})
|
||||
@@ -85,9 +79,9 @@ describe('<CompileAndDownloadProjectPDFButton />', function () {
|
||||
}) as HTMLButtonElement
|
||||
fireEvent.click(btn)
|
||||
|
||||
await waitFor(() => {
|
||||
screen.getByText(`${projectsData[0].name}: PDF unavailable for download`)
|
||||
})
|
||||
expect(assignStub).to.have.not.been.called
|
||||
await screen.findByText(
|
||||
`${projectsData[0].name}: PDF unavailable for download`
|
||||
)
|
||||
expect(this.locationWrapperStub.assign).to.have.not.been.called
|
||||
})
|
||||
})
|
||||
|
||||
+5
-11
@@ -3,24 +3,17 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import sinon from 'sinon'
|
||||
import { DownloadProjectButtonTooltip } from '../../../../../../../../frontend/js/features/project-list/components/table/cells/action-buttons/download-project-button'
|
||||
import { projectsData } from '../../../../fixtures/projects-data'
|
||||
import * as useLocationModule from '../../../../../../../../frontend/js/shared/hooks/use-location'
|
||||
import { location } from '@/shared/components/location'
|
||||
|
||||
describe('<DownloadProjectButton />', function () {
|
||||
let assignStub: sinon.SinonStub
|
||||
|
||||
beforeEach(function () {
|
||||
assignStub = sinon.stub()
|
||||
this.locationStub = sinon.stub(useLocationModule, 'useLocation').returns({
|
||||
assign: assignStub,
|
||||
replace: sinon.stub(),
|
||||
reload: sinon.stub(),
|
||||
setHash: sinon.stub(),
|
||||
})
|
||||
this.locationWrapperSandbox = sinon.createSandbox()
|
||||
this.locationWrapperStub = this.locationWrapperSandbox.stub(location)
|
||||
render(<DownloadProjectButtonTooltip project={projectsData[0]} />)
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
this.locationStub.restore()
|
||||
this.locationWrapperSandbox.restore()
|
||||
})
|
||||
|
||||
it('renders tooltip for button', async function () {
|
||||
@@ -35,6 +28,7 @@ describe('<DownloadProjectButton />', function () {
|
||||
}) as HTMLButtonElement
|
||||
fireEvent.click(btn)
|
||||
|
||||
const assignStub = this.locationWrapperStub.assign
|
||||
await waitFor(() => {
|
||||
expect(assignStub).to.have.been.called
|
||||
})
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ describe('<InlineTags />', function () {
|
||||
const removeButton = screen.getByRole('button', {
|
||||
name: 'Remove tag My Test Tag',
|
||||
})
|
||||
await fireEvent.click(removeButton)
|
||||
fireEvent.click(removeButton)
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
fetchMock.callHistory.called(
|
||||
|
||||
+41
-19
@@ -1,4 +1,4 @@
|
||||
import { screen, within, fireEvent } from '@testing-library/react'
|
||||
import { screen, within, fireEvent, waitFor } from '@testing-library/react'
|
||||
import { expect } from 'chai'
|
||||
import ProjectListTable from '../../../../../../frontend/js/features/project-list/components/table/project-list-table'
|
||||
import { currentProjects } from '../../fixtures/projects-data'
|
||||
@@ -67,9 +67,13 @@ describe('<ProjectListTable />', function () {
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.getAllByRole('row').length).to.equal(
|
||||
currentProjects.length + 1
|
||||
)
|
||||
)
|
||||
const rows = screen.getAllByRole('row')
|
||||
rows.shift() // remove first row since it's the header
|
||||
expect(rows.length).to.equal(currentProjects.length)
|
||||
|
||||
// Project name cell
|
||||
currentProjects.forEach(project => {
|
||||
@@ -139,42 +143,60 @@ describe('<ProjectListTable />', function () {
|
||||
it('selects all projects when header checkbox checked', async function () {
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
await fetchMock.callHistory.flush(true)
|
||||
const checkbox = screen.getByLabelText('Select all projects')
|
||||
const checkbox = await screen.findByLabelText('Select all projects')
|
||||
fireEvent.click(checkbox)
|
||||
const allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
const allCheckboxesChecked = allCheckboxes.filter(c => c.checked)
|
||||
// + 1 because of select all checkbox
|
||||
expect(allCheckboxesChecked.length).to.equal(currentProjects.length + 1)
|
||||
|
||||
await waitFor(() => {
|
||||
const allCheckboxes = screen.queryAllByRole<HTMLInputElement>('checkbox')
|
||||
const allCheckboxesChecked = allCheckboxes.filter(c => c.checked)
|
||||
// + 1 because of select all checkbox
|
||||
expect(allCheckboxesChecked.length).to.equal(currentProjects.length + 1)
|
||||
})
|
||||
})
|
||||
|
||||
it('unselects all projects when select all checkbox uchecked', async function () {
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
await fetchMock.callHistory.flush(true)
|
||||
const checkbox = screen.getByLabelText('Select all projects')
|
||||
const checkbox = await screen.findByLabelText('Select all projects')
|
||||
fireEvent.click(checkbox)
|
||||
fireEvent.click(checkbox)
|
||||
const allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
const allCheckboxesChecked = allCheckboxes.filter(c => c.checked)
|
||||
expect(allCheckboxesChecked.length).to.equal(0)
|
||||
|
||||
await waitFor(() => {
|
||||
const allCheckboxes = screen.queryAllByRole<HTMLInputElement>('checkbox')
|
||||
const allCheckboxesChecked = allCheckboxes.filter(c => c.checked)
|
||||
expect(allCheckboxesChecked.length).to.equal(0)
|
||||
})
|
||||
})
|
||||
|
||||
it('unselects select all projects checkbox when one project is unchecked', async function () {
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
await fetchMock.callHistory.flush(true)
|
||||
const checkbox = screen.getByLabelText('Select all projects')
|
||||
const checkbox = await screen.findByLabelText('Select all projects')
|
||||
fireEvent.click(checkbox)
|
||||
let allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
expect(allCheckboxes[1].getAttribute('data-project-id')).to.exist // make sure we are unchecking a project checkbox
|
||||
fireEvent.click(allCheckboxes[1])
|
||||
allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
const allCheckboxesChecked = allCheckboxes.filter(c => c.checked)
|
||||
expect(allCheckboxesChecked.length).to.equal(currentProjects.length - 1)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen
|
||||
.getAllByRole<HTMLInputElement>('checkbox')[1]
|
||||
.getAttribute('data-project-id')
|
||||
).to.exist // make sure we are unchecking a project checkbox
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getAllByRole<HTMLInputElement>('checkbox')[1])
|
||||
|
||||
await waitFor(() => {
|
||||
const allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
const allCheckboxesChecked = allCheckboxes.filter(c => c.checked)
|
||||
expect(allCheckboxesChecked.length).to.equal(currentProjects.length - 1)
|
||||
})
|
||||
})
|
||||
|
||||
it('only checks the checked project', async function () {
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
await fetchMock.callHistory.flush(true)
|
||||
const checkbox = screen.getByLabelText(`Select ${currentProjects[0].name}`)
|
||||
const checkbox = await screen.findByLabelText(
|
||||
`Select ${currentProjects[0].name}`
|
||||
)
|
||||
fireEvent.click(checkbox)
|
||||
const allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
const allCheckboxesChecked = allCheckboxes.filter(c => c.checked)
|
||||
|
||||
+18
-12
@@ -1,4 +1,4 @@
|
||||
import { render, screen, within } from '@testing-library/react'
|
||||
import { render, screen, waitFor, within } from '@testing-library/react'
|
||||
import { expect } from 'chai'
|
||||
import moment from 'moment/moment'
|
||||
import fetchMock from 'fetch-mock'
|
||||
@@ -68,24 +68,30 @@ describe('<ProjectTools />', function () {
|
||||
fetchMock.removeRoutes().clearHistory()
|
||||
})
|
||||
|
||||
it('does not show the Rename option for a project owned by a different user', function () {
|
||||
it('does not show the Rename option for a project owned by a different user', async function () {
|
||||
render(<ProjectListRootInner />)
|
||||
screen.getByLabelText('Select Starfleet Report (readAndWrite)').click()
|
||||
screen.getByRole('button', { name: 'More' }).click()
|
||||
expect(
|
||||
within(
|
||||
screen.getByTestId('project-tools-more-dropdown-menu')
|
||||
).queryByRole('menuitem', { name: 'Rename' })
|
||||
).to.be.null
|
||||
await waitFor(
|
||||
() =>
|
||||
expect(
|
||||
within(
|
||||
screen.getByTestId('project-tools-more-dropdown-menu')
|
||||
).queryByRole('menuitem', { name: 'Rename' })
|
||||
).to.be.null
|
||||
)
|
||||
})
|
||||
|
||||
it('displays the Rename option for a project owned by the current user', function () {
|
||||
it('displays the Rename option for a project owned by the current user', async function () {
|
||||
render(<ProjectListRootInner />)
|
||||
screen.getByLabelText('Select Starfleet Report (owner)').click()
|
||||
screen.getByRole('button', { name: 'More' }).click()
|
||||
within(screen.getByTestId('project-tools-more-dropdown-menu'))
|
||||
.getByRole('menuitem', { name: 'Rename' })
|
||||
.click()
|
||||
within(screen.getByRole('dialog')).getByText('Rename Project')
|
||||
const menu = await screen.findByTestId('project-tools-more-dropdown-menu')
|
||||
const menuItem = within(menu).getByRole('menuitem', {
|
||||
name: 'Rename',
|
||||
})
|
||||
menuItem.click()
|
||||
const dialog = await screen.findByRole('dialog')
|
||||
within(dialog).getByText('Rename Project')
|
||||
})
|
||||
})
|
||||
|
||||
+1
-1
@@ -92,6 +92,6 @@ describe('<RenameProjectModal />', function () {
|
||||
|
||||
await waitFor(() => expect(postRenameMock.callHistory.called()).to.be.true)
|
||||
|
||||
screen.getByText('Something went wrong. Please try again.')
|
||||
await screen.findByText('Something went wrong. Please try again.')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user