Merge pull request #9603 from overleaf/jel-project-tools
[web] Begin project tools for React dash GitOrigin-RevId: a735864153f836ca01135001c661aa31ec52cfa8
This commit is contained in:
+188
@@ -0,0 +1,188 @@
|
||||
import { fireEvent, screen, waitFor, within } from '@testing-library/react'
|
||||
import { expect } from 'chai'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import sinon from 'sinon'
|
||||
import ProjectListRoot from '../../../../../frontend/js/features/project-list/components/project-list-root'
|
||||
import { renderWithProjectListContext } from '../helpers/render-with-context'
|
||||
|
||||
const userId = '624333f147cfd8002622a1d3'
|
||||
|
||||
describe('<ProjectListRoot />', function () {
|
||||
const originalLocation = window.location
|
||||
const locationStub = sinon.stub()
|
||||
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
window.metaAttributesCache.set('ol-tags', [])
|
||||
window.metaAttributesCache.set('ol-ExposedSettings', { templateLinks: [] })
|
||||
window.user_id = userId
|
||||
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: { assign: locationStub },
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.user_id = undefined
|
||||
fetchMock.reset()
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: originalLocation,
|
||||
})
|
||||
})
|
||||
|
||||
describe('checkboxes', function () {
|
||||
let allCheckboxes: Array<HTMLInputElement> = []
|
||||
let toolbar: HTMLElement
|
||||
let project1Id: string | null, project2Id: string | null
|
||||
|
||||
beforeEach(async function () {
|
||||
renderWithProjectListContext(<ProjectListRoot />)
|
||||
await fetchMock.flush(true)
|
||||
await waitFor(() => {
|
||||
screen.findByRole('table')
|
||||
})
|
||||
})
|
||||
|
||||
describe('all projects', function () {
|
||||
beforeEach(function () {
|
||||
allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
// first one is the select all checkbox
|
||||
fireEvent.click(allCheckboxes[1])
|
||||
fireEvent.click(allCheckboxes[2])
|
||||
|
||||
project1Id = allCheckboxes[1].getAttribute('data-project-id')
|
||||
project2Id = allCheckboxes[2].getAttribute('data-project-id')
|
||||
toolbar = screen.getByRole('toolbar')
|
||||
})
|
||||
|
||||
it('downloads all selected projects and then unselects them', async function () {
|
||||
const downloadButton = within(toolbar).getByLabelText('Download')
|
||||
fireEvent.click(downloadButton)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(locationStub).to.have.been.called
|
||||
})
|
||||
|
||||
sinon.assert.calledWithMatch(
|
||||
locationStub,
|
||||
`/project/download/zip?project_ids=${project1Id},${project2Id}`
|
||||
)
|
||||
|
||||
const allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
const allCheckboxesChecked = allCheckboxes.filter(c => c.checked)
|
||||
expect(allCheckboxesChecked.length).to.equal(0)
|
||||
})
|
||||
|
||||
it('opens archive modal for all selected projects and archives all', async function () {
|
||||
fetchMock.post(
|
||||
`express:/project/${project1Id}/archive`,
|
||||
{
|
||||
status: 200,
|
||||
},
|
||||
{ delay: 0 }
|
||||
)
|
||||
fetchMock.post(
|
||||
`express:/project/${project2Id}/archive`,
|
||||
{
|
||||
status: 200,
|
||||
},
|
||||
{ delay: 0 }
|
||||
)
|
||||
|
||||
const archiveButton = within(toolbar).getByLabelText('Archive')
|
||||
fireEvent.click(archiveButton)
|
||||
|
||||
const confirmBtn = screen.getByText('Confirm') as HTMLButtonElement
|
||||
fireEvent.click(confirmBtn)
|
||||
expect(confirmBtn.disabled).to.be.true
|
||||
|
||||
await fetchMock.flush(true)
|
||||
expect(fetchMock.done()).to.be.true
|
||||
|
||||
const requests = fetchMock.calls()
|
||||
const [projectRequest1Url, projectRequest1Headers] = requests[2]
|
||||
expect(projectRequest1Url).to.equal(`/project/${project1Id}/archive`)
|
||||
expect(projectRequest1Headers?.method).to.equal('POST')
|
||||
const [projectRequest2Url, projectRequest2Headers] = requests[3]
|
||||
expect(projectRequest2Url).to.equal(`/project/${project2Id}/archive`)
|
||||
expect(projectRequest2Headers?.method).to.equal('POST')
|
||||
})
|
||||
|
||||
it('opens trash modal for all selected projects and trashes all', async function () {
|
||||
fetchMock.post(
|
||||
`express:/project/${project1Id}/trash`,
|
||||
{
|
||||
status: 200,
|
||||
},
|
||||
{ delay: 0 }
|
||||
)
|
||||
fetchMock.post(
|
||||
`express:/project/${project2Id}/trash`,
|
||||
{
|
||||
status: 200,
|
||||
},
|
||||
{ delay: 0 }
|
||||
)
|
||||
|
||||
const archiveButton = within(toolbar).getByLabelText('Trash')
|
||||
fireEvent.click(archiveButton)
|
||||
|
||||
const confirmBtn = screen.getByText('Confirm') as HTMLButtonElement
|
||||
fireEvent.click(confirmBtn)
|
||||
expect(confirmBtn.disabled).to.be.true
|
||||
|
||||
await fetchMock.flush(true)
|
||||
expect(fetchMock.done()).to.be.true
|
||||
|
||||
const requests = fetchMock.calls()
|
||||
const [projectRequest1Url, projectRequest1Headers] = requests[2]
|
||||
expect(projectRequest1Url).to.equal(`/project/${project1Id}/trash`)
|
||||
expect(projectRequest1Headers?.method).to.equal('POST')
|
||||
const [projectRequest2Url, projectRequest2Headers] = requests[3]
|
||||
expect(projectRequest2Url).to.equal(`/project/${project2Id}/trash`)
|
||||
expect(projectRequest2Headers?.method).to.equal('POST')
|
||||
})
|
||||
})
|
||||
|
||||
describe('archived projects', function () {
|
||||
beforeEach(function () {
|
||||
const filterButton = screen.getByText('Archived Projects')
|
||||
fireEvent.click(filterButton)
|
||||
|
||||
allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
expect(allCheckboxes.length === 2).to.be.true
|
||||
// first one is the select all checkbox
|
||||
fireEvent.click(allCheckboxes[1])
|
||||
project1Id = allCheckboxes[1].getAttribute('data-project-id')
|
||||
})
|
||||
it('does not show the archive button in toolbar when archive view selected', function () {
|
||||
expect(screen.queryByLabelText('Archive')).to.be.null
|
||||
})
|
||||
})
|
||||
|
||||
describe('trashed projects', function () {
|
||||
beforeEach(function () {
|
||||
const filterButton = screen.getByText('Trashed Projects')
|
||||
fireEvent.click(filterButton)
|
||||
|
||||
allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
// first one is the select all checkbox
|
||||
fireEvent.click(allCheckboxes[1])
|
||||
|
||||
project1Id = allCheckboxes[1].getAttribute('data-project-id')
|
||||
})
|
||||
it('does not show the trash button in toolbar when archive view selected', function () {
|
||||
expect(screen.queryByLabelText('Trash')).to.be.null
|
||||
})
|
||||
|
||||
it('clears selected projects when filter changed', function () {
|
||||
const filterButton = screen.getByText('All Projects')
|
||||
fireEvent.click(filterButton)
|
||||
|
||||
const allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
const allCheckboxesChecked = allCheckboxes.filter(c => c.checked)
|
||||
expect(allCheckboxesChecked.length).to.equal(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
+64
-40
@@ -1,20 +1,12 @@
|
||||
import { render, screen, within, fireEvent } from '@testing-library/react'
|
||||
import { screen, within, fireEvent } from '@testing-library/react'
|
||||
import { expect } from 'chai'
|
||||
import ProjectListTable from '../../../../../../frontend/js/features/project-list/components/table/project-list-table'
|
||||
import { ProjectListProvider } from '../../../../../../frontend/js/features/project-list/context/project-list-context'
|
||||
import { projectsData } from '../../fixtures/projects-data'
|
||||
import { currentProjects } from '../../fixtures/projects-data'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import { renderWithProjectListContext } from '../../helpers/render-with-context'
|
||||
|
||||
const userId = '624333f147cfd8002622a1d3'
|
||||
|
||||
const renderProjectListTableWithinProjectListProvider = () => {
|
||||
render(<ProjectListTable />, {
|
||||
wrapper: ({ children }) => (
|
||||
<ProjectListProvider>{children}</ProjectListProvider>
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
describe('<ProjectListTable />', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
@@ -29,12 +21,12 @@ describe('<ProjectListTable />', function () {
|
||||
})
|
||||
|
||||
it('renders the table', function () {
|
||||
renderProjectListTableWithinProjectListProvider()
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
screen.getByRole('table')
|
||||
})
|
||||
|
||||
it('sets aria-sort on column header currently sorted', function () {
|
||||
renderProjectListTableWithinProjectListProvider()
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
let foundSortedColumn = false
|
||||
const columns = screen.getAllByRole('columnheader')
|
||||
columns.forEach(col => {
|
||||
@@ -49,7 +41,7 @@ describe('<ProjectListTable />', function () {
|
||||
})
|
||||
|
||||
it('keeps the order type when selecting different column for sorting', function () {
|
||||
renderProjectListTableWithinProjectListProvider()
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
const lastModifiedBtn = screen.getByRole('button', {
|
||||
name: /last modified/i,
|
||||
})
|
||||
@@ -65,64 +57,51 @@ describe('<ProjectListTable />', function () {
|
||||
})
|
||||
|
||||
it('renders buttons for sorting all sortable columns', function () {
|
||||
renderProjectListTableWithinProjectListProvider()
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
screen.getByText('Sort by Title')
|
||||
screen.getByText('Sort by Owner')
|
||||
screen.getByText('Reverse Last Modified sort order') // currently sorted
|
||||
})
|
||||
|
||||
it('renders project title, owner, last modified, and action buttons', async function () {
|
||||
// archived and trashed projects are currently not shown
|
||||
const filteredProjects = projectsData.filter(
|
||||
({ archived, trashed }) => !archived && !trashed
|
||||
)
|
||||
|
||||
fetchMock.post('/api/project', {
|
||||
status: 200,
|
||||
body: {
|
||||
projects: filteredProjects,
|
||||
totalSize: filteredProjects.length,
|
||||
},
|
||||
})
|
||||
|
||||
renderProjectListTableWithinProjectListProvider()
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
await fetchMock.flush(true)
|
||||
|
||||
const rows = screen.getAllByRole('row')
|
||||
rows.shift() // remove first row since it's the header
|
||||
expect(rows.length).to.equal(filteredProjects.length)
|
||||
expect(rows.length).to.equal(currentProjects.length)
|
||||
|
||||
// Project name cell
|
||||
filteredProjects.forEach(project => {
|
||||
currentProjects.forEach(project => {
|
||||
screen.getByText(project.name)
|
||||
})
|
||||
|
||||
// Owner Column and Last Modified Column
|
||||
const row1 = screen
|
||||
.getByRole('cell', { name: filteredProjects[0].name })
|
||||
.getByRole('cell', { name: currentProjects[0].name })
|
||||
.closest('tr')!
|
||||
within(row1).getByText('You')
|
||||
within(row1).getByText('a day ago by Jean-Luc Picard')
|
||||
const row2 = screen
|
||||
.getByRole('cell', { name: filteredProjects[1].name })
|
||||
.getByRole('cell', { name: currentProjects[1].name })
|
||||
.closest('tr')!
|
||||
within(row2).getByText('Jean-Luc Picard')
|
||||
within(row2).getByText('7 days ago by Jean-Luc Picard')
|
||||
const row3 = screen
|
||||
.getByRole('cell', { name: filteredProjects[2].name })
|
||||
.getByRole('cell', { name: currentProjects[2].name })
|
||||
.closest('tr')!
|
||||
within(row3).getByText('worf@overleaf.com')
|
||||
within(row3).getByText('a month ago by worf@overleaf.com')
|
||||
// link sharing project
|
||||
const row4 = screen
|
||||
.getByRole('cell', { name: filteredProjects[3].name })
|
||||
.getByRole('cell', { name: currentProjects[3].name })
|
||||
.closest('tr')!
|
||||
within(row4).getByText('La Forge')
|
||||
within(row4).getByText('Link sharing')
|
||||
within(row4).getByText('2 months ago by La Forge')
|
||||
// link sharing read only, so it will not show an owner
|
||||
const row5 = screen
|
||||
.getByRole('cell', { name: filteredProjects[4].name })
|
||||
.getByRole('cell', { name: currentProjects[4].name })
|
||||
.closest('tr')!
|
||||
within(row5).getByText('Link sharing')
|
||||
within(row5).getByText('2 years ago')
|
||||
@@ -131,13 +110,13 @@ describe('<ProjectListTable />', function () {
|
||||
// temporary count tests until we add filtering for archived/trashed
|
||||
const copyButtons = screen.getAllByLabelText('Copy')
|
||||
screen.debug()
|
||||
expect(copyButtons.length).to.equal(filteredProjects.length)
|
||||
expect(copyButtons.length).to.equal(currentProjects.length)
|
||||
const downloadButtons = screen.getAllByLabelText('Download')
|
||||
expect(downloadButtons.length).to.equal(filteredProjects.length)
|
||||
expect(downloadButtons.length).to.equal(currentProjects.length)
|
||||
const archiveButtons = screen.getAllByLabelText('Archive')
|
||||
expect(archiveButtons.length).to.equal(filteredProjects.length)
|
||||
expect(archiveButtons.length).to.equal(currentProjects.length)
|
||||
const trashButtons = screen.getAllByLabelText('Trash')
|
||||
expect(trashButtons.length).to.equal(filteredProjects.length)
|
||||
expect(trashButtons.length).to.equal(currentProjects.length)
|
||||
|
||||
// TODO to be implemented when the component renders trashed & archived projects
|
||||
// const restoreButtons = screen.getAllByLabelText('Restore')
|
||||
@@ -145,4 +124,49 @@ describe('<ProjectListTable />', function () {
|
||||
// const deleteButtons = screen.getAllByLabelText('Delete')
|
||||
// expect(deleteButtons.length).to.equal(1)
|
||||
})
|
||||
|
||||
it('selects all projects when header checkbox checked', async function () {
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
await fetchMock.flush(true)
|
||||
const checkbox = screen.getByLabelText('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)
|
||||
})
|
||||
|
||||
it('unselects all projects when select all checkbox uchecked', async function () {
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
await fetchMock.flush(true)
|
||||
const checkbox = screen.getByLabelText('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)
|
||||
})
|
||||
|
||||
it('unselects select all projects checkbox when one project is unchecked', async function () {
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
await fetchMock.flush(true)
|
||||
const checkbox = screen.getByLabelText('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)
|
||||
})
|
||||
|
||||
it('only checks the checked project', async function () {
|
||||
renderWithProjectListContext(<ProjectListTable />)
|
||||
await fetchMock.flush(true)
|
||||
const checkbox = screen.getByLabelText(`Select ${currentProjects[0].name}`)
|
||||
fireEvent.click(checkbox)
|
||||
const allCheckboxes = screen.getAllByRole<HTMLInputElement>('checkbox')
|
||||
const allCheckboxesChecked = allCheckboxes.filter(c => c.checked)
|
||||
expect(allCheckboxesChecked.length).to.equal(1)
|
||||
})
|
||||
})
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import { fireEvent, screen } from '@testing-library/react'
|
||||
import ArchiveProjectsButton from '../../../../../../../../frontend/js/features/project-list/components/table/project-tools/buttons/archive-projects-button'
|
||||
import {
|
||||
resetProjectListContextFetch,
|
||||
renderWithProjectListContext,
|
||||
} from '../../../../helpers/render-with-context'
|
||||
|
||||
describe('<ArchiveProjectsButton />', function () {
|
||||
afterEach(function () {
|
||||
resetProjectListContextFetch()
|
||||
})
|
||||
|
||||
it('renders tooltip for button', function () {
|
||||
renderWithProjectListContext(<ArchiveProjectsButton />)
|
||||
const btn = screen.getByLabelText('Archive')
|
||||
fireEvent.mouseOver(btn)
|
||||
screen.getByRole('tooltip', { name: 'Archive' })
|
||||
})
|
||||
|
||||
it('opens the modal when clicked', function () {
|
||||
renderWithProjectListContext(<ArchiveProjectsButton />)
|
||||
const btn = screen.getByLabelText('Archive')
|
||||
fireEvent.click(btn)
|
||||
screen.getByText('Archive Projects')
|
||||
})
|
||||
})
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { fireEvent, screen } from '@testing-library/react'
|
||||
import DownloadProjectsButton from '../../../../../../../../frontend/js/features/project-list/components/table/project-tools/buttons/download-projects-button'
|
||||
import {
|
||||
resetProjectListContextFetch,
|
||||
renderWithProjectListContext,
|
||||
} from '../../../../helpers/render-with-context'
|
||||
|
||||
describe('<DownloadProjectsButton />', function () {
|
||||
afterEach(function () {
|
||||
resetProjectListContextFetch()
|
||||
})
|
||||
|
||||
it('renders tooltip for button', function () {
|
||||
renderWithProjectListContext(<DownloadProjectsButton />)
|
||||
const btn = screen.getByLabelText('Download')
|
||||
fireEvent.mouseOver(btn)
|
||||
screen.getByRole('tooltip', { name: 'Download' })
|
||||
})
|
||||
})
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import { fireEvent, screen } from '@testing-library/react'
|
||||
import TrashProjectsButton from '../../../../../../../../frontend/js/features/project-list/components/table/project-tools/buttons/trash-projects-button'
|
||||
import {
|
||||
resetProjectListContextFetch,
|
||||
renderWithProjectListContext,
|
||||
} from '../../../../helpers/render-with-context'
|
||||
|
||||
describe('<TrashProjectsButton />', function () {
|
||||
afterEach(function () {
|
||||
resetProjectListContextFetch()
|
||||
})
|
||||
|
||||
it('renders tooltip for button', function () {
|
||||
renderWithProjectListContext(<TrashProjectsButton />)
|
||||
const btn = screen.getByLabelText('Trash')
|
||||
fireEvent.mouseOver(btn)
|
||||
screen.getByRole('tooltip', { name: 'Trash' })
|
||||
})
|
||||
|
||||
it('opens the modal when clicked', function () {
|
||||
renderWithProjectListContext(<TrashProjectsButton />)
|
||||
const btn = screen.getByLabelText('Trash')
|
||||
fireEvent.click(btn)
|
||||
screen.getByText('Trash Projects')
|
||||
})
|
||||
})
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { screen } from '@testing-library/react'
|
||||
import { expect } from 'chai'
|
||||
import ProjectTools from '../../../../../../../frontend/js/features/project-list/components/table/project-tools/project-tools'
|
||||
import {
|
||||
renderWithProjectListContext,
|
||||
resetProjectListContextFetch,
|
||||
} from '../../../helpers/render-with-context'
|
||||
|
||||
describe('<ProjectListTable />', function () {
|
||||
afterEach(function () {
|
||||
resetProjectListContextFetch()
|
||||
})
|
||||
|
||||
it('renders the project tools', function () {
|
||||
renderWithProjectListContext(<ProjectTools />)
|
||||
expect(screen.getAllByRole('button').length).to.equal(3)
|
||||
screen.getByLabelText('Download')
|
||||
screen.getByLabelText('Archive')
|
||||
screen.getByLabelText('Trash')
|
||||
})
|
||||
})
|
||||
-15
@@ -13,12 +13,6 @@ describe('<ProjectsActionModal />', function () {
|
||||
const actionHandler = sinon.stub().resolves({})
|
||||
let sendSpy: sinon.SinonSpy
|
||||
|
||||
const modalText = {
|
||||
title: 'Action Title',
|
||||
top: <p>top text</p>,
|
||||
bottom: <b>bottom text</b>,
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
sendSpy = sinon.spy(eventTracking, 'send')
|
||||
})
|
||||
@@ -31,11 +25,8 @@ describe('<ProjectsActionModal />', function () {
|
||||
it('should handle the action passed', async function () {
|
||||
renderWithProjectListContext(
|
||||
<ProjectsActionModal
|
||||
title={modalText.title}
|
||||
action="archive"
|
||||
actionHandler={actionHandler}
|
||||
bodyTop={modalText.top}
|
||||
bodyBottom={modalText.bottom}
|
||||
projects={[projectsData[0], projectsData[1]]}
|
||||
handleCloseModal={() => {}}
|
||||
showModal
|
||||
@@ -58,11 +49,8 @@ describe('<ProjectsActionModal />', function () {
|
||||
|
||||
renderWithProjectListContext(
|
||||
<ProjectsActionModal
|
||||
title={modalText.title}
|
||||
action="archive"
|
||||
actionHandler={actionHandler}
|
||||
bodyTop={modalText.top}
|
||||
bodyBottom={modalText.bottom}
|
||||
projects={[
|
||||
projectsData[0],
|
||||
projectsData[1],
|
||||
@@ -91,11 +79,8 @@ describe('<ProjectsActionModal />', function () {
|
||||
it('should send an analytics even when opened', function () {
|
||||
renderWithProjectListContext(
|
||||
<ProjectsActionModal
|
||||
title={modalText.title}
|
||||
action="archive"
|
||||
actionHandler={actionHandler}
|
||||
bodyTop={modalText.top}
|
||||
bodyBottom={modalText.bottom}
|
||||
projects={[projectsData[0], projectsData[1]]}
|
||||
handleCloseModal={() => {}}
|
||||
showModal
|
||||
|
||||
@@ -128,3 +128,7 @@ export const projectsData: Array<Project> = [
|
||||
archivedProject,
|
||||
trashedProject,
|
||||
]
|
||||
|
||||
export const currentProjects: Array<Project> = projectsData.filter(
|
||||
({ archived, trashed }) => !archived && !trashed
|
||||
)
|
||||
|
||||
@@ -6,13 +6,13 @@ import fetchMock from 'fetch-mock'
|
||||
import { ProjectListProvider } from '../../../../../frontend/js/features/project-list/context/project-list-context'
|
||||
import { projectsData } from '../fixtures/projects-data'
|
||||
|
||||
export function renderWithProjectListContext(component, contextProps) {
|
||||
export function renderWithProjectListContext(component) {
|
||||
fetchMock.post('express:/api/project', {
|
||||
status: 200,
|
||||
body: { projects: projectsData },
|
||||
body: { projects: projectsData, totalSize: projectsData.length },
|
||||
})
|
||||
const ProjectListProviderWrapper = ({ children }) => (
|
||||
<ProjectListProvider {...contextProps}>{children}</ProjectListProvider>
|
||||
<ProjectListProvider>{children}</ProjectListProvider>
|
||||
)
|
||||
|
||||
return render(component, {
|
||||
|
||||
Reference in New Issue
Block a user