mirror of https://github.com/nextcloud/server.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
5.7 KiB
TypeScript
143 lines
5.7 KiB
TypeScript
2 months ago
|
import { describe, it, expect } from '@jest/globals'
|
||
|
|
||
|
import { FileSystemDirectoryEntry, FileSystemFileEntry, fileSystemEntryToDataTransferItem, DataTransferItem as DataTransferItemMock } from '../../../../__tests__/FileSystemAPIUtils'
|
||
|
import { join } from 'node:path'
|
||
|
import { Directory, traverseTree } from './DropServiceUtils'
|
||
|
import { dataTransferToFileTree } from './DropService'
|
||
|
import logger from '../logger'
|
||
|
|
||
|
const dataTree = {
|
||
|
'file0.txt': ['Hello, world!', 1234567890],
|
||
|
dir1: {
|
||
|
'file1.txt': ['Hello, world!', 4567891230],
|
||
|
'file2.txt': ['Hello, world!', 7891234560],
|
||
|
},
|
||
|
dir2: {
|
||
|
'file3.txt': ['Hello, world!', 1234567890],
|
||
|
},
|
||
|
}
|
||
|
|
||
|
// This is mocking a file tree using the FileSystem API
|
||
|
const buildFileSystemDirectoryEntry = (path: string, tree: any): FileSystemDirectoryEntry => {
|
||
|
const entries = Object.entries(tree).map(([name, contents]) => {
|
||
|
const fullPath = join(path, name)
|
||
|
if (Array.isArray(contents)) {
|
||
|
return new FileSystemFileEntry(fullPath, contents[0], contents[1])
|
||
|
} else {
|
||
|
return buildFileSystemDirectoryEntry(fullPath, contents)
|
||
|
}
|
||
|
})
|
||
|
return new FileSystemDirectoryEntry(path, entries)
|
||
|
}
|
||
|
|
||
|
const buildDataTransferItemArray = (path: string, tree: any, isFileSystemAPIAvailable = true): DataTransferItemMock[] => {
|
||
|
return Object.entries(tree).map(([name, contents]) => {
|
||
|
const fullPath = join(path, name)
|
||
|
if (Array.isArray(contents)) {
|
||
|
const entry = new FileSystemFileEntry(fullPath, contents[0], contents[1])
|
||
|
return fileSystemEntryToDataTransferItem(entry, isFileSystemAPIAvailable)
|
||
|
}
|
||
|
|
||
|
const entry = buildFileSystemDirectoryEntry(fullPath, contents)
|
||
|
return fileSystemEntryToDataTransferItem(entry, isFileSystemAPIAvailable)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
describe('Filesystem API traverseTree', () => {
|
||
|
it('Should traverse a file tree from root', async () => {
|
||
|
// Fake a FileSystemEntry tree
|
||
|
const root = buildFileSystemDirectoryEntry('root', dataTree)
|
||
|
const tree = await traverseTree(root as unknown as FileSystemEntry) as Directory
|
||
|
|
||
|
expect(tree.name).toBe('root')
|
||
|
expect(tree).toBeInstanceOf(Directory)
|
||
|
expect(tree.contents).toHaveLength(3)
|
||
|
expect(tree.size).toBe(13 * 4) // 13 bytes from 'Hello, world!'
|
||
|
})
|
||
|
|
||
|
it('Should traverse a file tree from a subdirectory', async () => {
|
||
|
// Fake a FileSystemEntry tree
|
||
|
const dir2 = buildFileSystemDirectoryEntry('dir2', dataTree.dir2)
|
||
|
const tree = await traverseTree(dir2 as unknown as FileSystemEntry) as Directory
|
||
|
|
||
|
expect(tree.name).toBe('dir2')
|
||
|
expect(tree).toBeInstanceOf(Directory)
|
||
|
expect(tree.contents).toHaveLength(1)
|
||
|
expect(tree.contents[0].name).toBe('file3.txt')
|
||
|
expect(tree.size).toBe(13) // 13 bytes from 'Hello, world!'
|
||
|
})
|
||
|
|
||
|
it('Should properly compute the last modified', async () => {
|
||
|
// Fake a FileSystemEntry tree
|
||
|
const root = buildFileSystemDirectoryEntry('root', dataTree)
|
||
|
const rootTree = await traverseTree(root as unknown as FileSystemEntry) as Directory
|
||
|
|
||
|
expect(rootTree.lastModified).toBe(7891234560)
|
||
|
|
||
|
// Fake a FileSystemEntry tree
|
||
|
const dir2 = buildFileSystemDirectoryEntry('root', dataTree.dir2)
|
||
|
const dir2Tree = await traverseTree(dir2 as unknown as FileSystemEntry) as Directory
|
||
|
expect(dir2Tree.lastModified).toBe(1234567890)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
describe('DropService dataTransferToFileTree', () => {
|
||
|
|
||
|
beforeAll(() => {
|
||
|
// DataTransferItem doesn't exists in jsdom, let's mock
|
||
|
// a dumb one so we can check the instanceof
|
||
|
// @ts-expect-error jsdom doesn't have DataTransferItem
|
||
|
window.DataTransferItem = DataTransferItemMock
|
||
|
})
|
||
|
|
||
|
afterAll(() => {
|
||
|
// @ts-expect-error jsdom doesn't have DataTransferItem
|
||
|
delete window.DataTransferItem
|
||
|
})
|
||
|
|
||
|
it('Should return a RootDirectory with Filesystem API', async () => {
|
||
|
jest.spyOn(logger, 'error').mockImplementation(() => jest.fn())
|
||
|
jest.spyOn(logger, 'warn').mockImplementation(() => jest.fn())
|
||
|
|
||
|
const dataTransferItems = buildDataTransferItemArray('root', dataTree)
|
||
|
const fileTree = await dataTransferToFileTree(dataTransferItems as unknown as DataTransferItem[])
|
||
|
|
||
|
expect(fileTree.name).toBe('root')
|
||
|
expect(fileTree).toBeInstanceOf(Directory)
|
||
|
expect(fileTree.contents).toHaveLength(3)
|
||
|
|
||
|
// The file tree should be recursive when using the Filesystem API
|
||
|
expect(fileTree.contents[1]).toBeInstanceOf(Directory)
|
||
|
expect((fileTree.contents[1] as Directory).contents).toHaveLength(2)
|
||
|
expect(fileTree.contents[2]).toBeInstanceOf(Directory)
|
||
|
expect((fileTree.contents[2] as Directory).contents).toHaveLength(1)
|
||
|
|
||
|
expect(logger.error).not.toBeCalled()
|
||
|
expect(logger.warn).not.toBeCalled()
|
||
|
})
|
||
|
|
||
|
it('Should return a RootDirectory with legacy File API ignoring recursive directories', async () => {
|
||
|
jest.spyOn(logger, 'error').mockImplementation(() => jest.fn())
|
||
|
jest.spyOn(logger, 'warn').mockImplementation(() => jest.fn())
|
||
|
|
||
|
const dataTransferItems = buildDataTransferItemArray('root', dataTree, false)
|
||
|
|
||
|
const fileTree = await dataTransferToFileTree(dataTransferItems as unknown as DataTransferItem[])
|
||
|
|
||
|
expect(fileTree.name).toBe('root')
|
||
|
expect(fileTree).toBeInstanceOf(Directory)
|
||
|
expect(fileTree.contents).toHaveLength(1)
|
||
|
|
||
|
// The file tree should be recursive when using the Filesystem API
|
||
|
expect(fileTree.contents[0]).not.toBeInstanceOf(Directory)
|
||
|
expect((fileTree.contents[0].name)).toBe('file0.txt')
|
||
|
|
||
|
expect(logger.error).not.toBeCalled()
|
||
|
expect(logger.warn).toHaveBeenNthCalledWith(1, 'Could not get FilesystemEntry of item, falling back to file')
|
||
|
expect(logger.warn).toHaveBeenNthCalledWith(2, 'Could not get FilesystemEntry of item, falling back to file')
|
||
|
expect(logger.warn).toHaveBeenNthCalledWith(3, 'Browser does not support Filesystem API. Directories will not be uploaded')
|
||
|
expect(logger.warn).toHaveBeenNthCalledWith(4, 'Could not get FilesystemEntry of item, falling back to file')
|
||
|
expect(logger.warn).toHaveBeenCalledTimes(4)
|
||
|
})
|
||
|
})
|