aboutsummaryrefslogtreecommitdiffstats
path: root/__tests__/FileSystemAPIUtils.ts
blob: d03bbf2d58652394bd96579a6fed35cc9961f334 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
 * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */
import { basename } from 'node:path'
import mime from 'mime'

class FileSystemEntry {

	private _isFile: boolean
	private _fullPath: string

	constructor(isFile: boolean, fullPath: string) {
		this._isFile = isFile
		this._fullPath = fullPath
	}

	get isFile() {
		return !!this._isFile
	}

	get isDirectory() {
		return !this.isFile
	}

	get name() {
		return basename(this._fullPath)
	}

}

export class FileSystemFileEntry extends FileSystemEntry {

	private _contents: string
	private _lastModified: number

	constructor(fullPath: string, contents: string, lastModified = Date.now()) {
		super(true, fullPath)
		this._contents = contents
		this._lastModified = lastModified
	}

	file(success: (file: File) => void) {
		const lastModified = this._lastModified
		// Faking the mime by using the file extension
		const type = mime.getType(this.name) || ''
		success(new File([this._contents], this.name, { lastModified, type }))
	}

}

export class FileSystemDirectoryEntry extends FileSystemEntry {

	private _entries: FileSystemEntry[]

	constructor(fullPath: string, entries: FileSystemEntry[]) {
		super(false, fullPath)
		this._entries = entries || []
	}

	createReader() {
		let read = false
		return {
			readEntries: (success: (entries: FileSystemEntry[]) => void) => {
				if (read) {
					return success([])
				}
				read = true
				success(this._entries)
			},
		}
	}

}

/**
 * This mocks the File API's File class
 * It will allow us to test the Filesystem API as well as the
 * File API in the same test suite.
 */
export class DataTransferItem {

	private _type: string
	private _entry: FileSystemEntry

	getAsEntry?: () => FileSystemEntry

	constructor(type = '', entry: FileSystemEntry, isFileSystemAPIAvailable = true) {
		this._type = type
		this._entry = entry

		// Only when the Files API is available we are
		// able to get the entry
		if (isFileSystemAPIAvailable) {
			this.getAsEntry = () => this._entry
		}
	}

	get kind() {
		return 'file'
	}

	get type() {
		return this._type
	}

	getAsFile(): File|null {
		if (this._entry.isFile && this._entry instanceof FileSystemFileEntry) {
			let file: File | null = null
			this._entry.file((f) => {
				file = f
			})
			return file
		}

		// The browser will return an empty File object if the entry is a directory
		return new File([], this._entry.name, { type: '' })
	}

}

export const fileSystemEntryToDataTransferItem = (entry: FileSystemEntry, isFileSystemAPIAvailable = true): DataTransferItem => {
	return new DataTransferItem(
		entry.isFile ? 'text/plain' : 'httpd/unix-directory',
		entry,
		isFileSystemAPIAvailable,
	)
}