@lvce-editor/shared-process 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +41 -0
- package/bin/sharedProcess.js +3 -0
- package/index.js +6 -0
- package/package.json +96 -0
- package/src/parts/Assert/Assert.js +57 -0
- package/src/parts/Callback/Callback.js +48 -0
- package/src/parts/ChildProcess/ChildProcess.js +98 -0
- package/src/parts/ClipBoard/ClipBoard.ipc.js +7 -0
- package/src/parts/ClipBoard/ClipBoard.js +23 -0
- package/src/parts/ClipBoard/ClipBoardGnome.js +78 -0
- package/src/parts/ClipBoard/ClipBoardNoop.js +14 -0
- package/src/parts/ClipBoard/ClipBoardWindows.js +22 -0
- package/src/parts/Command/Command.js +264 -0
- package/src/parts/Configuration/Configuration.ipc.js +7 -0
- package/src/parts/Configuration/Configuration.js +39 -0
- package/src/parts/Credentials/Credentials.ipc.js +10 -0
- package/src/parts/Credentials/Credentials.js +69 -0
- package/src/parts/Debug/Debug.js +3 -0
- package/src/parts/Developer/Developer.ipc.js +20 -0
- package/src/parts/Developer/Developer.js +132 -0
- package/src/parts/Download/Download.js +33 -0
- package/src/parts/Electron/Electron.ipc.js +19 -0
- package/src/parts/Electron/Electron.js +99 -0
- package/src/parts/Env/Env.js +3 -0
- package/src/parts/Error/Error.js +30 -0
- package/src/parts/ErrorHandling/ErrorHandling.js +40 -0
- package/src/parts/Exec/Exec.js +16 -0
- package/src/parts/Extension/Extension.js +7 -0
- package/src/parts/ExtensionHost/ExtensionHost.ipc.js +80 -0
- package/src/parts/ExtensionHost/ExtensionHost.js +163 -0
- package/src/parts/ExtensionHost/ExtensionHostBraceCompletion.js +14 -0
- package/src/parts/ExtensionHost/ExtensionHostClosingTag.js +14 -0
- package/src/parts/ExtensionHost/ExtensionHostColorTheme.js +60 -0
- package/src/parts/ExtensionHost/ExtensionHostCommand.js +19 -0
- package/src/parts/ExtensionHost/ExtensionHostCompletion.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostDefinition.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostDiagnostic.js +7 -0
- package/src/parts/ExtensionHost/ExtensionHostFileSystem.js +23 -0
- package/src/parts/ExtensionHost/ExtensionHostFormatting.js +4 -0
- package/src/parts/ExtensionHost/ExtensionHostHover.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostIconTheme.js +35 -0
- package/src/parts/ExtensionHost/ExtensionHostImplementation.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostKeyBindings.js +23 -0
- package/src/parts/ExtensionHost/ExtensionHostLanguages.js +84 -0
- package/src/parts/ExtensionHost/ExtensionHostManagement.js +26 -0
- package/src/parts/ExtensionHost/ExtensionHostOutput.js +3 -0
- package/src/parts/ExtensionHost/ExtensionHostQuickPick.js +6 -0
- package/src/parts/ExtensionHost/ExtensionHostReference.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostRename.js +27 -0
- package/src/parts/ExtensionHost/ExtensionHostSemanticTokens.js +10 -0
- package/src/parts/ExtensionHost/ExtensionHostSourceControl.js +15 -0
- package/src/parts/ExtensionHost/ExtensionHostStats.js +3 -0
- package/src/parts/ExtensionHost/ExtensionHostStatusBar.js +7 -0
- package/src/parts/ExtensionHost/ExtensionHostTabCompletion.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostTextDocument.js +35 -0
- package/src/parts/ExtensionHost/ExtensionHostTypeDefinition.js +12 -0
- package/src/parts/ExtensionHost/ExtensionHostWorkspace.js +3 -0
- package/src/parts/ExtensionManagement/ExtensionManagement.ipc.js +11 -0
- package/src/parts/ExtensionManagement/ExtensionManagement.js +319 -0
- package/src/parts/FileSystem/FileSystem.ipc.js +32 -0
- package/src/parts/FileSystem/FileSystem.js +228 -0
- package/src/parts/Git/Git.js +58 -0
- package/src/parts/Json/Json.js +67 -0
- package/src/parts/JsonFile/JsonFile.js +14 -0
- package/src/parts/JsonRpc/JsonRpc.js +22 -0
- package/src/parts/Native/Native.ipc.js +6 -0
- package/src/parts/Native/Native.js +14 -0
- package/src/parts/OutputChannel/OutputChannel.ipc.js +51 -0
- package/src/parts/OutputChannel/OutputChannel.js +37 -0
- package/src/parts/ParentIpc/ParentIpc.js +203 -0
- package/src/parts/Path/Path.js +17 -0
- package/src/parts/Platform/Platform.ipc.js +18 -0
- package/src/parts/Platform/Platform.js +165 -0
- package/src/parts/Preferences/Preferences.ipc.js +6 -0
- package/src/parts/Preferences/Preferences.js +75 -0
- package/src/parts/PrettyError/PrettyError.js +86 -0
- package/src/parts/Process/Process.ipc.js +7 -0
- package/src/parts/Process/Process.js +7 -0
- package/src/parts/Queue/Queue.js +35 -0
- package/src/parts/RequiresSocket/RequiresSocket.js +11 -0
- package/src/parts/RgPath/RgPath.js +1 -0
- package/src/parts/Root/Root.js +6 -0
- package/src/parts/Search/Search.ipc.js +6 -0
- package/src/parts/Search/Search.js +101 -0
- package/src/parts/SearchFile/SearchFile.ipc.js +6 -0
- package/src/parts/SearchFile/SearchFile.js +51 -0
- package/src/parts/Socket/Socket.js +132 -0
- package/src/parts/Stats/Stats.js +45 -0
- package/src/parts/Terminal/Terminal.ipc.js +45 -0
- package/src/parts/Terminal/Terminal.js +161 -0
- package/src/parts/TextDocument/TextDocument.ipc.js +6 -0
- package/src/parts/TextDocument/TextDocument.js +37 -0
- package/src/parts/Trace/Trace.js +15 -0
- package/src/parts/Trash/Trash.js +11 -0
- package/src/parts/WebSocketServer/WebSocketServer.ipc.js +6 -0
- package/src/parts/WebSocketServer/WebSocketServer.js +43 -0
- package/src/parts/Workspace/Workspace.ipc.js +7 -0
- package/src/parts/Workspace/Workspace.js +107 -0
- package/src/sharedProcessMain.js +61 -0
- package/test/Callback.test.js +42 -0
- package/test/ClipBoard.test.js +105 -0
- package/test/Credentials.test.js +147 -0
- package/test/Developer.test.js +34 -0
- package/test/Electron.test.js +93 -0
- package/test/Error.test.js +16 -0
- package/test/Exec.test.js +25 -0
- package/test/ExtensionHost.test.js +127 -0
- package/test/ExtensionHostColorTheme.test.js +141 -0
- package/test/ExtensionHostCommand.test.js +27 -0
- package/test/ExtensionHostCompletion.test.js +45 -0
- package/test/ExtensionHostDefinition.test.js +35 -0
- package/test/ExtensionHostDiagnostic.test.js +23 -0
- package/test/ExtensionHostFileSystem.test.js +91 -0
- package/test/ExtensionHostFormatting.test.js +27 -0
- package/test/ExtensionHostIconTheme.test.js +73 -0
- package/test/ExtensionHostLanguages.test.js +212 -0
- package/test/ExtensionHostOutput.test.js +23 -0
- package/test/ExtensionHostRename.test.js +59 -0
- package/test/ExtensionHostSemanticTokens.test.js +26 -0
- package/test/ExtensionHostTabCompletion.test.js +35 -0
- package/test/ExtensionHostTextDocument.test.js +61 -0
- package/test/ExtensionHostTypeDefinition.test.js +35 -0
- package/test/ExtensionHostWorkspace.test.js +21 -0
- package/test/ExtensionManagement.test.js +408 -0
- package/test/FileSystem.test.js +294 -0
- package/test/Json.test.js +25 -0
- package/test/Native.test.js +31 -0
- package/test/OutputChannel.test.js +68 -0
- package/test/Path.test.js +17 -0
- package/test/Platform.test.js +61 -0
- package/test/Preferences.test.js +140 -0
- package/test/Process.test.js +9 -0
- package/test/RgPath.test.js +5 -0
- package/test/Search.test.js +45 -0
- package/test/SearchFile.test.js +80 -0
- package/test/Terminal.test.js +53 -0
- package/test/Trash.test.js +34 -0
- package/test/WebSocketServer.test.js +98 -0
- package/test/fixture-search-1/index.html +10 -0
- package/test/fixture-search-file-1/fileA +0 -0
- package/test/fixture-search-file-1/fileB +0 -0
- package/test/fixture-search-file-1/nested/fileC +0 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import * as fs from 'node:fs'
|
|
2
|
+
import { mkdtemp, writeFile } from 'node:fs/promises'
|
|
3
|
+
import { tmpdir } from 'node:os'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
import { setTimeout } from 'node:timers/promises'
|
|
6
|
+
import * as FileSystem from '../src/parts/FileSystem/FileSystem.js'
|
|
7
|
+
|
|
8
|
+
const getTmpDir = () => {
|
|
9
|
+
return mkdtemp(join(tmpdir(), 'foo-'))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
test('copy - file', async () => {
|
|
13
|
+
const tmpDir1 = await getTmpDir()
|
|
14
|
+
const source = join(tmpDir1, 'a.txt')
|
|
15
|
+
await writeFile(source, 'a')
|
|
16
|
+
const tmpDir2 = await getTmpDir()
|
|
17
|
+
const target = join(tmpDir2, 'a.txt')
|
|
18
|
+
await FileSystem.copy(source, target)
|
|
19
|
+
expect(await fs.promises.readFile(target, 'utf-8')).toBe('a')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('copy - error - source does not exist', async () => {
|
|
23
|
+
const tmpDir1 = await getTmpDir()
|
|
24
|
+
const source = join(tmpDir1, 'a.txt')
|
|
25
|
+
const tmpDir2 = await getTmpDir()
|
|
26
|
+
const target = join(tmpDir2, 'a.txt')
|
|
27
|
+
await expect(FileSystem.copy(source, target)).rejects.toThrowError(
|
|
28
|
+
new Error(
|
|
29
|
+
`Failed to copy "${source}" to "${target}": ENOENT: no such file or directory, lstat '${source}'`
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('copy - to self', async () => {
|
|
35
|
+
const tmpDir1 = await getTmpDir()
|
|
36
|
+
const source = join(tmpDir1, 'a.txt')
|
|
37
|
+
await writeFile(source, 'a')
|
|
38
|
+
const target = source
|
|
39
|
+
await expect(FileSystem.copy(source, target)).rejects.toThrowError(
|
|
40
|
+
new Error(
|
|
41
|
+
`Failed to copy "${source}" to "${target}": Source and destination must not be the same.`
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('createFile', async () => {
|
|
47
|
+
const tmpDir = await getTmpDir()
|
|
48
|
+
const testFile = join(tmpDir, 'a.txt')
|
|
49
|
+
await FileSystem.createFile(testFile)
|
|
50
|
+
expect(await fs.promises.readFile(testFile, 'utf-8')).toBe('')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('createFile - should throw error if file already exists', async () => {
|
|
54
|
+
const tmpDir = await getTmpDir()
|
|
55
|
+
const testFile = join(tmpDir, 'a.txt')
|
|
56
|
+
await fs.promises.writeFile(testFile, 'abc')
|
|
57
|
+
expect(FileSystem.createFile(testFile)).rejects.toThrowError(
|
|
58
|
+
`Failed to create file "${testFile}": EEXIST: file already exists, open '${testFile}'`
|
|
59
|
+
)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
test('create folder', async () => {
|
|
63
|
+
const tmpDir = await getTmpDir()
|
|
64
|
+
const testFolder = join(tmpDir, 'a')
|
|
65
|
+
await FileSystem.createFolder(testFolder)
|
|
66
|
+
expect(await fs.promises.readdir(tmpDir)).toEqual(['a'])
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('create folder - should fail if folder already exists', async () => {
|
|
70
|
+
const tmpDir = await getTmpDir()
|
|
71
|
+
const testFolder = join(tmpDir, 'a')
|
|
72
|
+
await fs.promises.mkdir(testFolder)
|
|
73
|
+
expect(FileSystem.createFolder(testFolder)).rejects.toThrowError(
|
|
74
|
+
`Failed to create folder "${testFolder}": EEXIST: file already exists, mkdir '${testFolder}'`
|
|
75
|
+
)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// TODO test recursive create folder
|
|
79
|
+
|
|
80
|
+
test('writeFile', async () => {
|
|
81
|
+
const tmpDir = await getTmpDir()
|
|
82
|
+
const testFile = join(tmpDir, 'writefile.txt')
|
|
83
|
+
expect(await FileSystem.exists(testFile)).toBe(false)
|
|
84
|
+
await FileSystem.writeFile(testFile, 'Hello World')
|
|
85
|
+
expect(await fs.promises.readFile(testFile, 'utf-8')).toBe('Hello World')
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test('writeFile - nonexistent file', async () => {
|
|
89
|
+
const tmpDir = await getTmpDir()
|
|
90
|
+
const tmpFile = join(tmpDir, 'folder', 'non-existing-file.txt')
|
|
91
|
+
await expect(FileSystem.writeFile(tmpFile, 'Hello World')).rejects.toThrow(
|
|
92
|
+
`Failed to write to file "${tmpFile}": ENOENT`
|
|
93
|
+
)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test.skip('writeFile - parallel write on different files works', async () => {
|
|
97
|
+
// queue would be correct but slower
|
|
98
|
+
|
|
99
|
+
const tmpDir = await getTmpDir()
|
|
100
|
+
const testFile1 = join(tmpDir, 'writefile1.txt')
|
|
101
|
+
const testFile2 = join(tmpDir, 'writefile2.txt')
|
|
102
|
+
const testFile3 = join(tmpDir, 'writefile3.txt')
|
|
103
|
+
const testFile4 = join(tmpDir, 'writefile4.txt')
|
|
104
|
+
const testFile5 = join(tmpDir, 'writefile5.txt')
|
|
105
|
+
|
|
106
|
+
await Promise.all([
|
|
107
|
+
FileSystem.writeFile(testFile1, 'Hello World 1'),
|
|
108
|
+
FileSystem.writeFile(testFile2, 'Hello World 2'),
|
|
109
|
+
FileSystem.writeFile(testFile3, 'Hello World 3'),
|
|
110
|
+
FileSystem.writeFile(testFile4, 'Hello World 4'),
|
|
111
|
+
FileSystem.writeFile(testFile5, 'Hello World 5'),
|
|
112
|
+
])
|
|
113
|
+
expect(fs.readFileSync(testFile1, 'utf-8')).toBe('Hello World 1')
|
|
114
|
+
expect(fs.readFileSync(testFile2, 'utf-8')).toBe('Hello World 2')
|
|
115
|
+
expect(fs.readFileSync(testFile3, 'utf-8')).toBe('Hello World 3')
|
|
116
|
+
expect(fs.readFileSync(testFile4, 'utf-8')).toBe('Hello World 4')
|
|
117
|
+
expect(fs.readFileSync(testFile5, 'utf-8')).toBe('Hello World 5')
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test.skip('writeFile - parallel write on same files works and is sequentialized', async () => {
|
|
121
|
+
// queue would be correct but slower
|
|
122
|
+
|
|
123
|
+
const tmpDir = await getTmpDir()
|
|
124
|
+
const testFile = join(tmpDir, 'writefile.txt')
|
|
125
|
+
await Promise.all([
|
|
126
|
+
FileSystem.writeFile(testFile, 'Hello World 1'),
|
|
127
|
+
FileSystem.writeFile(testFile, 'Hello World 2'),
|
|
128
|
+
setTimeout(10).then(() => FileSystem.writeFile(testFile, 'Hello World 3')),
|
|
129
|
+
FileSystem.writeFile(testFile, 'Hello World 4'),
|
|
130
|
+
setTimeout(10).then(() => FileSystem.writeFile(testFile, 'Hello World 5')),
|
|
131
|
+
])
|
|
132
|
+
expect(fs.readFileSync(testFile, 'utf-8')).toBe('Hello World 5')
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
test('writeFile (string, error handling)', async () => {
|
|
136
|
+
const tmpDir = await getTmpDir()
|
|
137
|
+
const testFile = join(tmpDir, 'flushed.txt')
|
|
138
|
+
fs.mkdirSync(testFile) // this will trigger an error later because testFile is now a directory!
|
|
139
|
+
let expectedError
|
|
140
|
+
try {
|
|
141
|
+
await FileSystem.writeFile(testFile, 'Hello World')
|
|
142
|
+
} catch (error) {
|
|
143
|
+
expectedError = error
|
|
144
|
+
}
|
|
145
|
+
expect(expectedError).toBeDefined()
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
test('ensureFile - created parent folders recursively', async () => {
|
|
149
|
+
const tmpDir = await getTmpDir()
|
|
150
|
+
const testFile = join(tmpDir, 'a', 'b', 'c', 'd', 'writefile.txt')
|
|
151
|
+
expect(await FileSystem.exists(testFile)).toBe(false)
|
|
152
|
+
await FileSystem.ensureFile(testFile, 'Hello World')
|
|
153
|
+
expect(await fs.promises.readFile(testFile, 'utf-8')).toBe('Hello World')
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test('remove', async () => {
|
|
157
|
+
const tmpDir = await getTmpDir()
|
|
158
|
+
const testFile = join(tmpDir, 'file-to-be-removed.txt')
|
|
159
|
+
await fs.promises.writeFile(testFile, '')
|
|
160
|
+
await FileSystem.remove(testFile)
|
|
161
|
+
expect(fs.existsSync(testFile)).toBe(false)
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
test('remove - non-existing file', async () => {
|
|
165
|
+
const tmpDir = await getTmpDir()
|
|
166
|
+
const testFile = join(tmpDir, 'non-existing.txt')
|
|
167
|
+
await FileSystem.remove(testFile)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
test('rename', async () => {
|
|
171
|
+
const tmpDir = await getTmpDir()
|
|
172
|
+
const oldPath = join(tmpDir, 'file-to-be-moved.txt')
|
|
173
|
+
const newPath = join(tmpDir, 'file-has-been-moved.txt')
|
|
174
|
+
await fs.promises.writeFile(oldPath, '')
|
|
175
|
+
await FileSystem.rename(oldPath, newPath)
|
|
176
|
+
expect(fs.existsSync(oldPath)).toBe(false)
|
|
177
|
+
expect(fs.existsSync(newPath)).toBe(true)
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
test('rename - non existing old path', async () => {
|
|
181
|
+
const tmpDir = await getTmpDir()
|
|
182
|
+
const oldPath = join(tmpDir, 'non-existing.txt')
|
|
183
|
+
const newPath = join(tmpDir, 'file-has-been-moved.txt')
|
|
184
|
+
await expect(FileSystem.rename(oldPath, newPath)).rejects.toThrow(
|
|
185
|
+
`Failed to rename "${oldPath}" to "${newPath}": ENOENT`
|
|
186
|
+
)
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
test('rename - new path in non-existing nested directory', async () => {
|
|
190
|
+
const tmpDir = await getTmpDir()
|
|
191
|
+
const oldPath = join(tmpDir, 'file-to-be-moved.txt')
|
|
192
|
+
const newPath = join(tmpDir, 'nested/nested/nested/file-has-been-moved.txt')
|
|
193
|
+
await fs.promises.writeFile(oldPath, '')
|
|
194
|
+
await expect(FileSystem.rename(oldPath, newPath)).rejects.toThrow(
|
|
195
|
+
`Failed to rename "${oldPath}" to "${newPath}": ENOENT:`
|
|
196
|
+
)
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
const waitForWatcherReady = async (watcher) => {
|
|
200
|
+
await new Promise((resolve) => {
|
|
201
|
+
watcher.once('ready', async () => {
|
|
202
|
+
// try to fix tests on macos through timeout :/
|
|
203
|
+
await setTimeout(100)
|
|
204
|
+
resolve(undefined)
|
|
205
|
+
})
|
|
206
|
+
})
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// TODO all file watcher tests are very flaky on macos/windows ci
|
|
210
|
+
|
|
211
|
+
test.skip('watch - add', async () => {
|
|
212
|
+
const tmpDir = await getTmpDir()
|
|
213
|
+
const watcher = FileSystem.watch(tmpDir)
|
|
214
|
+
const events = []
|
|
215
|
+
let _resolve
|
|
216
|
+
let i = 0
|
|
217
|
+
await waitForWatcherReady(watcher)
|
|
218
|
+
watcher.on('all', (...args) => {
|
|
219
|
+
events.push([args[0], args[1]])
|
|
220
|
+
i++
|
|
221
|
+
if (i === 2) {
|
|
222
|
+
_resolve()
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
const resolvePromise = new Promise((resolve) => {
|
|
226
|
+
_resolve = resolve
|
|
227
|
+
})
|
|
228
|
+
await fs.promises.writeFile(join(tmpDir, 'abc.txt'), 'sample text')
|
|
229
|
+
await fs.promises.writeFile(join(tmpDir, 'def.txt'), 'sample text')
|
|
230
|
+
await resolvePromise
|
|
231
|
+
await setTimeout(1000)
|
|
232
|
+
expect(events).toEqual([
|
|
233
|
+
['add', join(tmpDir, 'abc.txt')],
|
|
234
|
+
['add', join(tmpDir, 'def.txt')],
|
|
235
|
+
])
|
|
236
|
+
watcher.close()
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
test.skip('watch - remove', async () => {
|
|
240
|
+
const tmpDir = await getTmpDir()
|
|
241
|
+
await fs.promises.writeFile(join(tmpDir, 'abc.txt'), 'sample text')
|
|
242
|
+
const watcher = FileSystem.watch(tmpDir)
|
|
243
|
+
const events = []
|
|
244
|
+
let _resolve
|
|
245
|
+
let i = 0
|
|
246
|
+
await waitForWatcherReady(watcher)
|
|
247
|
+
watcher.on('all', (...args) => {
|
|
248
|
+
events.push([args[0], args[1]])
|
|
249
|
+
i++
|
|
250
|
+
if (i === 1) {
|
|
251
|
+
_resolve()
|
|
252
|
+
}
|
|
253
|
+
})
|
|
254
|
+
const resolvePromise = new Promise((resolve) => {
|
|
255
|
+
_resolve = resolve
|
|
256
|
+
})
|
|
257
|
+
await fs.promises.rm(join(tmpDir, 'abc.txt'))
|
|
258
|
+
await resolvePromise
|
|
259
|
+
await setTimeout(1000)
|
|
260
|
+
expect(events).toEqual([['unlink', join(tmpDir, 'abc.txt')]])
|
|
261
|
+
watcher.close()
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
test.skip('watch - rename', async () => {
|
|
265
|
+
const tmpDir = await getTmpDir()
|
|
266
|
+
await fs.promises.writeFile(join(tmpDir, 'abc.txt'), 'sample text')
|
|
267
|
+
const watcher = FileSystem.watch(tmpDir)
|
|
268
|
+
const events = []
|
|
269
|
+
let _resolve
|
|
270
|
+
let i = 0
|
|
271
|
+
await waitForWatcherReady(watcher)
|
|
272
|
+
watcher.on('all', (...args) => {
|
|
273
|
+
events.push([args[0], args[1]])
|
|
274
|
+
i++
|
|
275
|
+
if (i === 2) {
|
|
276
|
+
_resolve()
|
|
277
|
+
}
|
|
278
|
+
})
|
|
279
|
+
const resolvePromise = new Promise((resolve) => {
|
|
280
|
+
_resolve = resolve
|
|
281
|
+
})
|
|
282
|
+
await fs.promises.rename(join(tmpDir, 'abc.txt'), join(tmpDir, 'def.txt'))
|
|
283
|
+
await resolvePromise
|
|
284
|
+
await setTimeout(1000)
|
|
285
|
+
expect(events).toEqual([
|
|
286
|
+
['add', join(tmpDir, 'def.txt')],
|
|
287
|
+
['unlink', join(tmpDir, 'abc.txt')],
|
|
288
|
+
])
|
|
289
|
+
watcher.close()
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
test('getPathSeparator', () => {
|
|
293
|
+
expect(FileSystem.getPathSeparator()).toEqual(expect.any(String))
|
|
294
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as Json from '../src/parts/Json/Json.js'
|
|
2
|
+
|
|
3
|
+
test('parse', async () => {
|
|
4
|
+
expect(await Json.parse('{ "x": 42 }')).toEqual({ x: 42 })
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
test('parse - syntax error', async () => {
|
|
8
|
+
await expect(
|
|
9
|
+
Json.parse('{ "x" 42 }', '/test/some-file.txt')
|
|
10
|
+
).rejects.toThrowError(
|
|
11
|
+
/^Unexpected number in JSON at position 6 while parsing/
|
|
12
|
+
)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('stringify', () => {
|
|
16
|
+
expect(Json.stringify({ x: 42 })).toBe(`{
|
|
17
|
+
"x": 42
|
|
18
|
+
}
|
|
19
|
+
`)
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('stringify - invalid parameter', () => {
|
|
23
|
+
expect(Json.stringify(Symbol('a'))).toBe(`undefined
|
|
24
|
+
`)
|
|
25
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jest } from '@jest/globals'
|
|
2
|
+
|
|
3
|
+
jest.unstable_mockModule('open', () => {
|
|
4
|
+
return {
|
|
5
|
+
default: jest.fn(() => {
|
|
6
|
+
throw new Error('not implemented')
|
|
7
|
+
}),
|
|
8
|
+
}
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
const open = await import('open')
|
|
12
|
+
const Native = await import('../src/parts/Native/Native.js')
|
|
13
|
+
|
|
14
|
+
test('openFolder', async () => {
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
open.default.mockImplementation(() => {})
|
|
17
|
+
await Native.openFolder('/test')
|
|
18
|
+
expect(open.default).toHaveBeenCalledTimes(1)
|
|
19
|
+
expect(open.default).toHaveBeenCalledWith('/test')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('openFolder - error', async () => {
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
open.default.mockImplementation(() => {
|
|
25
|
+
throw new TypeError('x is not a function')
|
|
26
|
+
})
|
|
27
|
+
// TODO should say that is is a TypeError
|
|
28
|
+
await expect(Native.openFolder('/test')).rejects.toThrowError(
|
|
29
|
+
new Error('Failed to open /test: x is not a function')
|
|
30
|
+
)
|
|
31
|
+
})
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { createWriteStream } from 'node:fs'
|
|
2
|
+
import * as fs from 'node:fs/promises'
|
|
3
|
+
import { mkdtemp } from 'node:fs/promises'
|
|
4
|
+
import { tmpdir } from 'node:os'
|
|
5
|
+
import { join } from 'node:path'
|
|
6
|
+
import { jest } from '@jest/globals'
|
|
7
|
+
import waitForExpect from 'wait-for-expect'
|
|
8
|
+
import * as OutputChannel from '../src/parts/OutputChannel/OutputChannel.js'
|
|
9
|
+
import * as Platform from '../src/parts/Platform/Platform.js'
|
|
10
|
+
|
|
11
|
+
const getTmpDir = () => {
|
|
12
|
+
return mkdtemp(join(tmpdir(), 'foo-'))
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (Platform.isWindows()) {
|
|
16
|
+
test.todo('output channel test')
|
|
17
|
+
} else {
|
|
18
|
+
test('writing to channel via stream', async () => {
|
|
19
|
+
const tmpDir = await getTmpDir()
|
|
20
|
+
await fs.writeFile(join(tmpDir, 'log.txt'), '')
|
|
21
|
+
const onData = jest.fn()
|
|
22
|
+
const state = OutputChannel.open(join(tmpDir, 'log.txt'), onData)
|
|
23
|
+
const writeStream = createWriteStream(join(tmpDir, 'log.txt'))
|
|
24
|
+
writeStream.write('a')
|
|
25
|
+
await waitForExpect(() => {
|
|
26
|
+
expect(onData).toHaveBeenNthCalledWith(1, 'a')
|
|
27
|
+
})
|
|
28
|
+
writeStream.write('b')
|
|
29
|
+
await waitForExpect(() => {
|
|
30
|
+
expect(onData).toHaveBeenNthCalledWith(2, 'b')
|
|
31
|
+
})
|
|
32
|
+
writeStream.write('c')
|
|
33
|
+
writeStream.close()
|
|
34
|
+
await waitForExpect(() => {
|
|
35
|
+
expect(onData).toHaveBeenNthCalledWith(3, 'c')
|
|
36
|
+
})
|
|
37
|
+
OutputChannel.dispose(state)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('writing to channel', async () => {
|
|
41
|
+
const tmpDir = await getTmpDir()
|
|
42
|
+
await fs.writeFile(join(tmpDir, 'log.txt'), '')
|
|
43
|
+
const onData = jest.fn()
|
|
44
|
+
const state = OutputChannel.open(join(tmpDir, 'log.txt'), onData)
|
|
45
|
+
await fs.writeFile(join(tmpDir, 'log.txt'), 'abc\n')
|
|
46
|
+
await waitForExpect(() => {
|
|
47
|
+
expect(onData).toHaveBeenCalledWith('abc\n')
|
|
48
|
+
})
|
|
49
|
+
OutputChannel.dispose(state)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test('non-existing file', async () => {
|
|
53
|
+
const tmpDir = await getTmpDir()
|
|
54
|
+
const onData = jest.fn()
|
|
55
|
+
const onError = jest.fn()
|
|
56
|
+
const state = OutputChannel.open(
|
|
57
|
+
join(tmpDir, 'non-existing-file.txt'),
|
|
58
|
+
onData,
|
|
59
|
+
onError
|
|
60
|
+
)
|
|
61
|
+
expect(onError).toHaveBeenCalledWith(
|
|
62
|
+
expect.stringMatching(
|
|
63
|
+
/^Error: ENOENT: no such file or directory, access /
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
OutputChannel.dispose(state)
|
|
67
|
+
})
|
|
68
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as Path from '../src/parts/Path/Path.js'
|
|
2
|
+
|
|
3
|
+
test('join', () => {
|
|
4
|
+
if (process.platform === 'win32') {
|
|
5
|
+
expect(Path.join('test', 'my-file.txt')).toBe('test\\my-file.txt')
|
|
6
|
+
} else {
|
|
7
|
+
expect(Path.join('test', 'my-file.txt')).toBe('test/my-file.txt')
|
|
8
|
+
}
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
test('dirname', () => {
|
|
12
|
+
if (process.platform === 'win32') {
|
|
13
|
+
expect(Path.dirname('test\\my-file.txt')).toBe('test')
|
|
14
|
+
} else {
|
|
15
|
+
expect(Path.dirname('test/my-file.txt')).toBe('test')
|
|
16
|
+
}
|
|
17
|
+
})
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as Platform from '../src/parts/Platform/Platform.js'
|
|
2
|
+
|
|
3
|
+
test('isWindows', () => {
|
|
4
|
+
expect(Platform.isWindows()).toEqual(expect.any(Boolean))
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
test('isMacOs', () => {
|
|
8
|
+
expect(Platform.isMacOs()).toEqual(expect.any(Boolean))
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
test('getDataDir', () => {
|
|
12
|
+
expect(Platform.getDataDir()).toEqual(expect.any(String))
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('getConfigDir', () => {
|
|
16
|
+
expect(Platform.getConfigDir()).toEqual(expect.any(String))
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('getCacheDir', () => {
|
|
20
|
+
expect(Platform.getCacheDir()).toEqual(expect.any(String))
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test('getHomeDir', () => {
|
|
24
|
+
expect(Platform.getHomeDir()).toEqual(expect.any(String))
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('getCachedExtensionsPath', () => {
|
|
28
|
+
expect(Platform.getCachedExtensionsPath()).toEqual(expect.any(String))
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('getBuiltinExtensionsPath', () => {
|
|
32
|
+
expect(Platform.getBuiltinExtensionsPath()).toEqual(expect.any(String))
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('getDisabledExtensionsPath', () => {
|
|
36
|
+
expect(Platform.getDisabledExtensionsPath()).toEqual(expect.any(String))
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('getMarketplaceUrl', () => {
|
|
40
|
+
expect(Platform.getMarketplaceUrl()).toEqual(expect.any(String))
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('getDesktop', () => {
|
|
44
|
+
expect(Platform.getDesktop()).toEqual(expect.any(String))
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('getPathSeparator', () => {
|
|
48
|
+
expect(Platform.getPathSeparator()).toEqual(expect.any(String))
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('getLogsDir', () => {
|
|
52
|
+
expect(Platform.getLogsDir()).toEqual(expect.any(String))
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('getUserSettingsPath', () => {
|
|
56
|
+
expect(Platform.getUserSettingsPath()).toEqual(expect.any(String))
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('getRecentlyOpenedPath', () => {
|
|
60
|
+
expect(Platform.getRecentlyOpenedPath()).toEqual(expect.any(String))
|
|
61
|
+
})
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { mkdtemp, readFile, writeFile, mkdir } from 'node:fs/promises'
|
|
2
|
+
import { tmpdir } from 'node:os'
|
|
3
|
+
import { join } from 'node:path'
|
|
4
|
+
import * as Platform from '../src/parts/Platform/Platform.js'
|
|
5
|
+
import * as Preferences from '../src/parts/Preferences/Preferences.js'
|
|
6
|
+
|
|
7
|
+
const getTmpDir = () => {
|
|
8
|
+
return mkdtemp(join(tmpdir(), 'foo-'))
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// test.skip('getAll - no preferences exist', async () => {
|
|
12
|
+
// const tmpDir = await getTmpDir()
|
|
13
|
+
// Platform.state.getConfigDir = () => {
|
|
14
|
+
// return tmpDir
|
|
15
|
+
// }
|
|
16
|
+
// expect(await Preferences.getAll()).toEqual({
|
|
17
|
+
// 'editor.fontFamily': "'Fira Code'",
|
|
18
|
+
// 'editor.fontSize': 14,
|
|
19
|
+
// 'extensions.autoUpdate': true,
|
|
20
|
+
// 'workbench.activityBar.visible': true,
|
|
21
|
+
// 'workbench.colorTheme': 'slime',
|
|
22
|
+
// 'workbench.iconTheme': 'vscode-icons',
|
|
23
|
+
// 'workbench.sideBar.visible': true,
|
|
24
|
+
// })
|
|
25
|
+
// })
|
|
26
|
+
|
|
27
|
+
// test('set - no preferences exist', async () => {
|
|
28
|
+
// const tmpDir = await getTmpDir()
|
|
29
|
+
// Platform.state.getConfigDir = () => {
|
|
30
|
+
// return tmpDir
|
|
31
|
+
// }
|
|
32
|
+
// await Preferences.set('sample-key', 'sample-value')
|
|
33
|
+
// expect(await readFile(join(tmpDir, 'settings.json'), 'utf-8')).toBe(`{
|
|
34
|
+
// \"sample-key\": \"sample-value\"
|
|
35
|
+
// }
|
|
36
|
+
// `)
|
|
37
|
+
// })
|
|
38
|
+
|
|
39
|
+
// test('set - no preferences exist in nested folder', async () => {
|
|
40
|
+
// const tmpDir = await getTmpDir()
|
|
41
|
+
// Platform.state.getConfigDir = () => {
|
|
42
|
+
// return join(tmpDir, 'my-app', 'nested')
|
|
43
|
+
// }
|
|
44
|
+
// await Preferences.set('sample-key', 'sample-value')
|
|
45
|
+
// expect(
|
|
46
|
+
// await readFile(join(tmpDir, 'my-app', 'nested', 'settings.json'), 'utf-8')
|
|
47
|
+
// ).toBe(`{
|
|
48
|
+
// \"sample-key\": \"sample-value\"
|
|
49
|
+
// }
|
|
50
|
+
// `)
|
|
51
|
+
// })
|
|
52
|
+
|
|
53
|
+
// test('set - preferences exist', async () => {
|
|
54
|
+
// const tmpDir = await getTmpDir()
|
|
55
|
+
// Platform.state.getConfigDir = () => {
|
|
56
|
+
// return tmpDir
|
|
57
|
+
// }
|
|
58
|
+
// await writeFile(
|
|
59
|
+
// join(tmpDir, 'settings.json'),
|
|
60
|
+
// JSON.stringify({
|
|
61
|
+
// 'key-0': '0',
|
|
62
|
+
// }) + '\n'
|
|
63
|
+
// )
|
|
64
|
+
// await Preferences.set('sample-key', 'sample-value')
|
|
65
|
+
// expect(await readFile(join(tmpDir, 'settings.json'), 'utf-8')).toBe(`{
|
|
66
|
+
// \"key-0\": \"0\",
|
|
67
|
+
// \"sample-key\": \"sample-value\"
|
|
68
|
+
// }
|
|
69
|
+
// `)
|
|
70
|
+
// })
|
|
71
|
+
|
|
72
|
+
// test.skip('set - preferences exist but are invalid json', async () => {
|
|
73
|
+
// const tmpDir = await getTmpDir()
|
|
74
|
+
// Platform.state.getConfigDir = () => {
|
|
75
|
+
// return tmpDir
|
|
76
|
+
// }
|
|
77
|
+
// const settingsPath = join(tmpDir, 'settings.json')
|
|
78
|
+
// await writeFile(settingsPath, `"`)
|
|
79
|
+
// // TODO should handle error gracefully
|
|
80
|
+
// await expect(
|
|
81
|
+
// Preferences.set('sample-key', 'sample-value')
|
|
82
|
+
// ).rejects.toThrowError(
|
|
83
|
+
// new Error(
|
|
84
|
+
// `Unexpected end of JSON input while parsing "\\"" in ${settingsPath}`
|
|
85
|
+
// )
|
|
86
|
+
// )
|
|
87
|
+
// })
|
|
88
|
+
|
|
89
|
+
test('getAll - error', async () => {
|
|
90
|
+
const tmpDir = await getTmpDir()
|
|
91
|
+
Platform.state.getAppDir = () => {
|
|
92
|
+
return tmpDir
|
|
93
|
+
}
|
|
94
|
+
await expect(Preferences.getAll()).rejects.toThrowError(
|
|
95
|
+
/^Failed to get all preferences: Failed to load default preferences: ENOENT/
|
|
96
|
+
)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
// test('getDefaultPreferences - error', async () => {
|
|
100
|
+
// const tmpDir = await getTmpDir()
|
|
101
|
+
// Platform.state.getAppDir = () => {
|
|
102
|
+
// return tmpDir
|
|
103
|
+
// }
|
|
104
|
+
// await expect(Preferences.getDefaultPreferences()).rejects.toThrowError(
|
|
105
|
+
// /^Failed to load default preferences: ENOENT/
|
|
106
|
+
// )
|
|
107
|
+
// })
|
|
108
|
+
|
|
109
|
+
// test('set - error', async () => {
|
|
110
|
+
// const tmpDir = await getTmpDir()
|
|
111
|
+
// await mkdir(join(tmpDir, 'settings.json'))
|
|
112
|
+
// Platform.state.getConfigDir = () => {
|
|
113
|
+
// return tmpDir
|
|
114
|
+
// }
|
|
115
|
+
// await expect(Preferences.set('x', 42)).rejects.toThrowError(
|
|
116
|
+
// /^Failed to set key in user settings: failed to get user preferences: EISDIR/
|
|
117
|
+
// )
|
|
118
|
+
// })
|
|
119
|
+
|
|
120
|
+
// test('getUserSettingsContent - error', async () => {
|
|
121
|
+
// const tmpDir = await getTmpDir()
|
|
122
|
+
// await mkdir(join(tmpDir, 'settings.json'))
|
|
123
|
+
// Platform.state.getConfigDir = () => {
|
|
124
|
+
// return tmpDir
|
|
125
|
+
// }
|
|
126
|
+
// await expect(Preferences.getUserSettingsContent()).rejects.toThrowError(
|
|
127
|
+
// /^Failed to load user settings: EISDIR/
|
|
128
|
+
// )
|
|
129
|
+
// })
|
|
130
|
+
|
|
131
|
+
// test('setUserSettingsContent - error', async () => {
|
|
132
|
+
// const tmpDir = await getTmpDir()
|
|
133
|
+
// await mkdir(join(tmpDir, 'settings.json'))
|
|
134
|
+
// Platform.state.getConfigDir = () => {
|
|
135
|
+
// return tmpDir
|
|
136
|
+
// }
|
|
137
|
+
// await expect(Preferences.setUserSettingsContent('')).rejects.toThrowError(
|
|
138
|
+
// /^Failed to write to user settings file: EISDIR/
|
|
139
|
+
// )
|
|
140
|
+
// })
|