mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 13:13:45 +01:00
Merge pull request #36230 from overleaf/ii-workspaces-projects-page
Empty states for the project list views GitOrigin-RevId: 3ce8e327bb675f3c63763e7599396020a4252025
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
import NoProjects from '@/features/project-list/components/no-projects'
|
||||
import {
|
||||
Filter,
|
||||
ProjectListProvider,
|
||||
} from '@/features/project-list/context/project-list-context'
|
||||
import { SplitTestProvider } from '@/shared/context/split-test-context'
|
||||
|
||||
describe('<NoProjects />', function () {
|
||||
beforeEach(function () {
|
||||
cy.intercept('post', '/api/project', {
|
||||
body: { projects: [], totalSize: 0 },
|
||||
})
|
||||
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-ExposedSettings', {
|
||||
isOverleaf: true,
|
||||
templateLinks: [],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const setGroupPlan = () =>
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-usersBestSubscription', {
|
||||
type: 'group',
|
||||
})
|
||||
})
|
||||
|
||||
const setIndividualPlan = () =>
|
||||
cy.window().then(win => {
|
||||
win.metaAttributesCache.set('ol-usersBestSubscription', {
|
||||
type: 'individual',
|
||||
})
|
||||
})
|
||||
|
||||
const mountNoProjects = (
|
||||
activeSection: Filter,
|
||||
showNewProjectButton = false
|
||||
) =>
|
||||
cy.mount(
|
||||
<SplitTestProvider>
|
||||
<ProjectListProvider>
|
||||
<NoProjects
|
||||
activeSection={activeSection}
|
||||
showNewProjectButton={showNewProjectButton}
|
||||
/>
|
||||
</ProjectListProvider>
|
||||
</SplitTestProvider>
|
||||
)
|
||||
|
||||
describe('all projects', function () {
|
||||
it('shows the generic empty state', function () {
|
||||
mountNoProjects('all')
|
||||
|
||||
cy.findByText('No projects yet').should('be.visible')
|
||||
cy.findByText(
|
||||
'Projects you own or have access to will appear here.'
|
||||
).should('be.visible')
|
||||
})
|
||||
})
|
||||
|
||||
describe('your projects', function () {
|
||||
it('shows the non-group copy when the user is not on a group plan', function () {
|
||||
setIndividualPlan()
|
||||
mountNoProjects('owned')
|
||||
|
||||
cy.findByText('No projects yet').should('be.visible')
|
||||
cy.findByText('Projects you create will appear here.').should(
|
||||
'be.visible'
|
||||
)
|
||||
cy.findByText(
|
||||
'Projects you create across all your workspaces will appear here.'
|
||||
).should('not.exist')
|
||||
})
|
||||
|
||||
it('shows the workspaces copy when the user is on a group plan', function () {
|
||||
setGroupPlan()
|
||||
mountNoProjects('owned')
|
||||
|
||||
cy.findByText('No projects yet').should('be.visible')
|
||||
cy.findByText(
|
||||
'Projects you create across all your workspaces will appear here.'
|
||||
).should('be.visible')
|
||||
cy.findByText('Projects you create will appear here.').should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('shared with you', function () {
|
||||
it('shows the non-group copy when the user is not on a group plan', function () {
|
||||
setIndividualPlan()
|
||||
mountNoProjects('shared')
|
||||
|
||||
cy.findByText('Nothing shared with you yet').should('be.visible')
|
||||
cy.findByText(
|
||||
'Projects shared with you directly will appear here.'
|
||||
).should('be.visible')
|
||||
cy.findByText(
|
||||
'Projects shared with you directly, or ones you’ve joined in a shared workspace, will appear here.'
|
||||
).should('not.exist')
|
||||
})
|
||||
|
||||
it('shows the workspaces copy when the user is on a group plan', function () {
|
||||
setGroupPlan()
|
||||
mountNoProjects('shared')
|
||||
|
||||
cy.findByText('Nothing shared with you yet').should('be.visible')
|
||||
cy.findByText(
|
||||
'Projects shared with you directly, or ones you’ve joined in a shared workspace, will appear here.'
|
||||
).should('be.visible')
|
||||
cy.findByText(
|
||||
'Projects shared with you directly will appear here.'
|
||||
).should('not.exist')
|
||||
})
|
||||
})
|
||||
|
||||
describe('archived projects', function () {
|
||||
it('shows the archived empty state', function () {
|
||||
mountNoProjects('archived')
|
||||
|
||||
cy.findByText('No archived projects').should('be.visible')
|
||||
cy.findByText(
|
||||
'Projects you archive will appear here. Archiving won’t affect anyone else working on the project.'
|
||||
).should('be.visible')
|
||||
})
|
||||
})
|
||||
|
||||
describe('trashed projects', function () {
|
||||
it('shows the trashed empty state with the restore hint', function () {
|
||||
mountNoProjects('trashed')
|
||||
|
||||
cy.findByText('No trashed projects').should('be.visible')
|
||||
cy.findByText(/projects you trash will appear here/i).should('be.visible')
|
||||
cy.findByText(
|
||||
/you can restore or permanently delete them at any time/i
|
||||
).should('be.visible')
|
||||
})
|
||||
})
|
||||
|
||||
describe('new project button', function () {
|
||||
it('shows the button when showNewProjectButton is true', function () {
|
||||
mountNoProjects('all', true)
|
||||
|
||||
cy.findByRole('button', { name: 'New project' }).should('be.visible')
|
||||
})
|
||||
|
||||
it('hides the button when showNewProjectButton is false', function () {
|
||||
mountNoProjects('all', false)
|
||||
|
||||
cy.findByText('No projects yet').should('be.visible')
|
||||
cy.findByRole('button', { name: 'New project' }).should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
+54
@@ -1,6 +1,8 @@
|
||||
import { screen, within, fireEvent, waitFor } from '@testing-library/react'
|
||||
import { expect } from 'chai'
|
||||
import { useEffect } from 'react'
|
||||
import ProjectListTable from '../../../../../../frontend/js/features/project-list/components/table/project-list-table'
|
||||
import { useProjectListContext } from '@/features/project-list/context/project-list-context'
|
||||
import { currentProjects } from '../../fixtures/projects-data'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import { renderWithProjectListContext } from '../../helpers/render-with-context'
|
||||
@@ -236,4 +238,56 @@ describe('<ProjectListTable />', function () {
|
||||
const allCheckboxesChecked = allCheckboxes.filter(c => c.checked)
|
||||
expect(allCheckboxesChecked.length).to.equal(1)
|
||||
})
|
||||
|
||||
describe('when no projects are visible', function () {
|
||||
function SetSearchText({ value }: { value: string }) {
|
||||
const { setSearchText } = useProjectListContext()
|
||||
useEffect(() => {
|
||||
setSearchText(value)
|
||||
}, [setSearchText, value])
|
||||
return null
|
||||
}
|
||||
|
||||
const renderWithSearchText = (
|
||||
value: string,
|
||||
options?: { projects?: typeof currentProjects }
|
||||
) =>
|
||||
renderWithProjectListContext(
|
||||
<>
|
||||
<SetSearchText value={value} />
|
||||
<ProjectListTable />
|
||||
</>,
|
||||
options
|
||||
)
|
||||
|
||||
it('names the search query when the shared-workspace split test is enabled', async function () {
|
||||
window.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'shared-workspace': 'enabled',
|
||||
})
|
||||
renderWithSearchText('Literature review')
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
await screen.findByText('No projects match “Literature review”')
|
||||
})
|
||||
|
||||
it('does not name the search query when the split test is disabled', async function () {
|
||||
window.metaAttributesCache.set('ol-splitTestVariants', {})
|
||||
renderWithSearchText('Literature review')
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
await screen.findByText('No projects')
|
||||
expect(screen.queryByText('No projects match “Literature review”')).to.be
|
||||
.null
|
||||
})
|
||||
|
||||
it('shows the generic message when there is no search query', async function () {
|
||||
window.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'shared-workspace': 'enabled',
|
||||
})
|
||||
renderWithSearchText('', { projects: [] })
|
||||
await fetchMock.callHistory.flush(true)
|
||||
|
||||
await screen.findByText('No projects')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user