|
@@ -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 { expect } from 'chai'
|
|
|
import ProjectListTable from '../../../../../../frontend/js/features/project-list/components/table/project-list-table'
|
|
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 fetchMock from 'fetch-mock'
|
|
|
|
|
+import { renderWithProjectListContext } from '../../helpers/render-with-context'
|
|
|
|
|
|
|
|
const userId = '624333f147cfd8002622a1d3'
|
|
const userId = '624333f147cfd8002622a1d3'
|
|
|
|
|
|
|
|
-const renderProjectListTableWithinProjectListProvider = () => {
|
|
|
|
|
- render(<ProjectListTable />, {
|
|
|
|
|
- wrapper: ({ children }) => (
|
|
|
|
|
- <ProjectListProvider>{children}</ProjectListProvider>
|
|
|
|
|
- ),
|
|
|
|
|
- })
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
describe('<ProjectListTable />', function () {
|
|
describe('<ProjectListTable />', function () {
|
|
|
beforeEach(function () {
|
|
beforeEach(function () {
|
|
|
window.metaAttributesCache = new Map()
|
|
window.metaAttributesCache = new Map()
|
|
@@ -29,12 +21,12 @@ describe('<ProjectListTable />', function () {
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
it('renders the table', function () {
|
|
it('renders the table', function () {
|
|
|
- renderProjectListTableWithinProjectListProvider()
|
|
|
|
|
|
|
+ renderWithProjectListContext(<ProjectListTable />)
|
|
|
screen.getByRole('table')
|
|
screen.getByRole('table')
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
it('sets aria-sort on column header currently sorted', function () {
|
|
it('sets aria-sort on column header currently sorted', function () {
|
|
|
- renderProjectListTableWithinProjectListProvider()
|
|
|
|
|
|
|
+ renderWithProjectListContext(<ProjectListTable />)
|
|
|
let foundSortedColumn = false
|
|
let foundSortedColumn = false
|
|
|
const columns = screen.getAllByRole('columnheader')
|
|
const columns = screen.getAllByRole('columnheader')
|
|
|
columns.forEach(col => {
|
|
columns.forEach(col => {
|
|
@@ -49,7 +41,7 @@ describe('<ProjectListTable />', function () {
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
it('keeps the order type when selecting different column for sorting', function () {
|
|
it('keeps the order type when selecting different column for sorting', function () {
|
|
|
- renderProjectListTableWithinProjectListProvider()
|
|
|
|
|
|
|
+ renderWithProjectListContext(<ProjectListTable />)
|
|
|
const lastModifiedBtn = screen.getByRole('button', {
|
|
const lastModifiedBtn = screen.getByRole('button', {
|
|
|
name: /last modified/i,
|
|
name: /last modified/i,
|
|
|
})
|
|
})
|
|
@@ -65,64 +57,51 @@ describe('<ProjectListTable />', function () {
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
it('renders buttons for sorting all sortable columns', function () {
|
|
it('renders buttons for sorting all sortable columns', function () {
|
|
|
- renderProjectListTableWithinProjectListProvider()
|
|
|
|
|
|
|
+ renderWithProjectListContext(<ProjectListTable />)
|
|
|
screen.getByText('Sort by Title')
|
|
screen.getByText('Sort by Title')
|
|
|
screen.getByText('Sort by Owner')
|
|
screen.getByText('Sort by Owner')
|
|
|
screen.getByText('Reverse Last Modified sort order') // currently sorted
|
|
screen.getByText('Reverse Last Modified sort order') // currently sorted
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
it('renders project title, owner, last modified, and action buttons', async function () {
|
|
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)
|
|
await fetchMock.flush(true)
|
|
|
|
|
|
|
|
const rows = screen.getAllByRole('row')
|
|
const rows = screen.getAllByRole('row')
|
|
|
rows.shift() // remove first row since it's the header
|
|
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
|
|
// Project name cell
|
|
|
- filteredProjects.forEach(project => {
|
|
|
|
|
|
|
+ currentProjects.forEach(project => {
|
|
|
screen.getByText(project.name)
|
|
screen.getByText(project.name)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
// Owner Column and Last Modified Column
|
|
// Owner Column and Last Modified Column
|
|
|
const row1 = screen
|
|
const row1 = screen
|
|
|
- .getByRole('cell', { name: filteredProjects[0].name })
|
|
|
|
|
|
|
+ .getByRole('cell', { name: currentProjects[0].name })
|
|
|
.closest('tr')!
|
|
.closest('tr')!
|
|
|
within(row1).getByText('You')
|
|
within(row1).getByText('You')
|
|
|
within(row1).getByText('a day ago by Jean-Luc Picard')
|
|
within(row1).getByText('a day ago by Jean-Luc Picard')
|
|
|
const row2 = screen
|
|
const row2 = screen
|
|
|
- .getByRole('cell', { name: filteredProjects[1].name })
|
|
|
|
|
|
|
+ .getByRole('cell', { name: currentProjects[1].name })
|
|
|
.closest('tr')!
|
|
.closest('tr')!
|
|
|
within(row2).getByText('Jean-Luc Picard')
|
|
within(row2).getByText('Jean-Luc Picard')
|
|
|
within(row2).getByText('7 days ago by Jean-Luc Picard')
|
|
within(row2).getByText('7 days ago by Jean-Luc Picard')
|
|
|
const row3 = screen
|
|
const row3 = screen
|
|
|
- .getByRole('cell', { name: filteredProjects[2].name })
|
|
|
|
|
|
|
+ .getByRole('cell', { name: currentProjects[2].name })
|
|
|
.closest('tr')!
|
|
.closest('tr')!
|
|
|
within(row3).getByText('worf@overleaf.com')
|
|
within(row3).getByText('worf@overleaf.com')
|
|
|
within(row3).getByText('a month ago by worf@overleaf.com')
|
|
within(row3).getByText('a month ago by worf@overleaf.com')
|
|
|
// link sharing project
|
|
// link sharing project
|
|
|
const row4 = screen
|
|
const row4 = screen
|
|
|
- .getByRole('cell', { name: filteredProjects[3].name })
|
|
|
|
|
|
|
+ .getByRole('cell', { name: currentProjects[3].name })
|
|
|
.closest('tr')!
|
|
.closest('tr')!
|
|
|
within(row4).getByText('La Forge')
|
|
within(row4).getByText('La Forge')
|
|
|
within(row4).getByText('Link sharing')
|
|
within(row4).getByText('Link sharing')
|
|
|
within(row4).getByText('2 months ago by La Forge')
|
|
within(row4).getByText('2 months ago by La Forge')
|
|
|
// link sharing read only, so it will not show an owner
|
|
// link sharing read only, so it will not show an owner
|
|
|
const row5 = screen
|
|
const row5 = screen
|
|
|
- .getByRole('cell', { name: filteredProjects[4].name })
|
|
|
|
|
|
|
+ .getByRole('cell', { name: currentProjects[4].name })
|
|
|
.closest('tr')!
|
|
.closest('tr')!
|
|
|
within(row5).getByText('Link sharing')
|
|
within(row5).getByText('Link sharing')
|
|
|
within(row5).getByText('2 years ago')
|
|
within(row5).getByText('2 years ago')
|
|
@@ -131,13 +110,13 @@ describe('<ProjectListTable />', function () {
|
|
|
// temporary count tests until we add filtering for archived/trashed
|
|
// temporary count tests until we add filtering for archived/trashed
|
|
|
const copyButtons = screen.getAllByLabelText('Copy')
|
|
const copyButtons = screen.getAllByLabelText('Copy')
|
|
|
screen.debug()
|
|
screen.debug()
|
|
|
- expect(copyButtons.length).to.equal(filteredProjects.length)
|
|
|
|
|
|
|
+ expect(copyButtons.length).to.equal(currentProjects.length)
|
|
|
const downloadButtons = screen.getAllByLabelText('Download')
|
|
const downloadButtons = screen.getAllByLabelText('Download')
|
|
|
- expect(downloadButtons.length).to.equal(filteredProjects.length)
|
|
|
|
|
|
|
+ expect(downloadButtons.length).to.equal(currentProjects.length)
|
|
|
const archiveButtons = screen.getAllByLabelText('Archive')
|
|
const archiveButtons = screen.getAllByLabelText('Archive')
|
|
|
- expect(archiveButtons.length).to.equal(filteredProjects.length)
|
|
|
|
|
|
|
+ expect(archiveButtons.length).to.equal(currentProjects.length)
|
|
|
const trashButtons = screen.getAllByLabelText('Trash')
|
|
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
|
|
// TODO to be implemented when the component renders trashed & archived projects
|
|
|
// const restoreButtons = screen.getAllByLabelText('Restore')
|
|
// const restoreButtons = screen.getAllByLabelText('Restore')
|
|
@@ -145,4 +124,49 @@ describe('<ProjectListTable />', function () {
|
|
|
// const deleteButtons = screen.getAllByLabelText('Delete')
|
|
// const deleteButtons = screen.getAllByLabelText('Delete')
|
|
|
// expect(deleteButtons.length).to.equal(1)
|
|
// 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)
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|