mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #3548 from overleaf/ta-file-tree-init-fix
[ReactFileTree] Fix Initial State When Selected File Doesn't Exist GitOrigin-RevId: 92ee8573203e66abf26c9b3afab2fccd90ec8c2e
This commit is contained in:
parent
759fbe8587
commit
d121b81896
5 changed files with 78 additions and 8 deletions
|
@ -82,13 +82,26 @@ export function FileTreeSelectableProvider({
|
|||
rootDocId
|
||||
)
|
||||
|
||||
const { fileTreeData } = useFileTreeMutable()
|
||||
|
||||
const [selectedEntityIds, dispatch] = useReducer(
|
||||
hasWritePermissions
|
||||
? fileTreeSelectableReadWriteReducer
|
||||
: fileTreeSelectableReadOnlyReducer,
|
||||
initialSelectedEntityId ? new Set([initialSelectedEntityId]) : new Set()
|
||||
null,
|
||||
() => {
|
||||
if (!initialSelectedEntityId) return new Set()
|
||||
|
||||
// the entity with id=initialSelectedEntityId might not exist in the tree
|
||||
// anymore. This checks that it exists before initialising the reducer
|
||||
// with the id.
|
||||
if (findInTree(fileTreeData, initialSelectedEntityId))
|
||||
return new Set([initialSelectedEntityId])
|
||||
|
||||
// the entity doesn't exist anymore; don't select any files
|
||||
return new Set()
|
||||
}
|
||||
)
|
||||
const { fileTreeData } = useFileTreeMutable()
|
||||
|
||||
const [selectedEntityParentIds, setSelectedEntityParentIds] = useState(
|
||||
new Set()
|
||||
|
|
|
@ -65,15 +65,15 @@ describe('<FileTreeFolderList/>', function() {
|
|||
{ _id: '3', name: '3.tex' }
|
||||
]
|
||||
renderWithContext(
|
||||
<FileTreeFolderList folders={[]} docs={docs} files={[]} />,
|
||||
{ contextProps: { rootDocId: '1' } }
|
||||
<FileTreeFolderList folders={[]} docs={docs} files={[]} />
|
||||
)
|
||||
|
||||
const treeitem1 = screen.getByRole('treeitem', { name: '1.tex' })
|
||||
const treeitem2 = screen.getByRole('treeitem', { name: '2.tex' })
|
||||
const treeitem3 = screen.getByRole('treeitem', { name: '3.tex' })
|
||||
|
||||
// item 1 i selected by default
|
||||
// click item 1: it gets selected
|
||||
fireEvent.click(treeitem1)
|
||||
screen.getByRole('treeitem', { name: '1.tex', selected: true })
|
||||
screen.getByRole('treeitem', { name: '2.tex', selected: false })
|
||||
screen.getByRole('treeitem', { name: '3.tex', selected: false })
|
||||
|
|
|
@ -69,7 +69,19 @@ describe('<FileTreeitemInner />', function() {
|
|||
it('starts rename on menu item click', function() {
|
||||
renderWithContext(
|
||||
<FileTreeitemInner id="123abc" name="bar.tex" isSelected />,
|
||||
{ contextProps: { rootDocId: '123abc' } }
|
||||
{
|
||||
contextProps: {
|
||||
rootDocId: '123abc',
|
||||
rootFolder: [
|
||||
{
|
||||
_id: 'root-folder-id',
|
||||
docs: [{ _id: '123abc', name: 'bar.tex' }],
|
||||
folders: [],
|
||||
fileRefs: []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const renameButton = screen.getByRole('menuitem', { name: 'Rename' })
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react'
|
||||
import sinon from 'sinon'
|
||||
import { screen, render, fireEvent } from '@testing-library/react'
|
||||
import { screen, render, fireEvent, waitFor } from '@testing-library/react'
|
||||
import fetchMock from 'fetch-mock'
|
||||
|
||||
import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root'
|
||||
|
@ -18,6 +18,7 @@ describe('<FileTreeRoot/>', function() {
|
|||
fetchMock.restore()
|
||||
onSelect.reset()
|
||||
onInit.reset()
|
||||
global.localStorage.clear()
|
||||
})
|
||||
|
||||
it('renders', function() {
|
||||
|
@ -45,6 +46,40 @@ describe('<FileTreeRoot/>', function() {
|
|||
screen.getByRole('treeitem', { name: 'main.tex', selected: true })
|
||||
})
|
||||
|
||||
it('renders with invalid selected doc in local storage', async function() {
|
||||
global.localStorage.setItem(
|
||||
'doc.open_id.123abc',
|
||||
JSON.stringify('not-a-valid-id')
|
||||
)
|
||||
const rootFolder = [
|
||||
{
|
||||
_id: 'root-folder-id',
|
||||
docs: [{ _id: '456def', name: 'main.tex' }],
|
||||
folders: [],
|
||||
fileRefs: []
|
||||
}
|
||||
]
|
||||
render(
|
||||
<FileTreeRoot
|
||||
rootFolder={rootFolder}
|
||||
projectId="123abc"
|
||||
hasWritePermissions
|
||||
rootDocId="456def"
|
||||
onSelect={onSelect}
|
||||
onInit={onInit}
|
||||
/>
|
||||
)
|
||||
|
||||
// as a proxy to check that the invalid entity ha not been select we start
|
||||
// a delete and ensure the modal is displayed (the cancel button can be
|
||||
// selected) This is needed to make sure the test fail.
|
||||
const treeitemFile = screen.getByRole('treeitem', { name: 'main.tex' })
|
||||
fireEvent.click(treeitemFile, { ctrlKey: true })
|
||||
const deleteButton = screen.getByRole('menuitem', { name: 'Delete' })
|
||||
fireEvent.click(deleteButton)
|
||||
await waitFor(() => screen.getByRole('button', { name: 'Cancel' }))
|
||||
})
|
||||
|
||||
it('fire onSelect', function() {
|
||||
const rootFolder = [
|
||||
{
|
||||
|
|
|
@ -30,7 +30,17 @@ describe('<FileTreeToolbar/>', function() {
|
|||
|
||||
it('with one selected file', function() {
|
||||
renderWithContext(<FileTreeToolbar />, {
|
||||
contextProps: { rootDocId: '123abc' }
|
||||
contextProps: {
|
||||
rootDocId: '456def',
|
||||
rootFolder: [
|
||||
{
|
||||
_id: 'root-folder-id',
|
||||
docs: [{ _id: '456def', name: 'main.tex' }],
|
||||
folders: [],
|
||||
fileRefs: []
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
screen.getByRole('button', { name: 'New File' })
|
||||
|
|
Loading…
Reference in a new issue