@lvce-editor/shared-process 0.0.2 → 0.0.6

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.
Files changed (56) hide show
  1. package/config/builtinCommands.json +367 -0
  2. package/config/colorTheme.json +98 -0
  3. package/config/defaultKeyBindings.json +649 -0
  4. package/config/defaultSettings.json +17 -0
  5. package/extensions/builtin.theme-slime/README.md +5 -0
  6. package/extensions/builtin.theme-slime/color-theme.json +205 -0
  7. package/extensions/builtin.theme-slime/extension.json +13 -0
  8. package/extensions/builtin.theme-slime/icon.png +0 -0
  9. package/package.json +3 -3
  10. package/src/parts/Env/Env.js +1 -1
  11. package/src/parts/Platform/Platform.js +7 -0
  12. package/src/parts/Preferences/Preferences.js +3 -6
  13. package/src/parts/Root/Root.js +1 -1
  14. package/test/Callback.test.js +0 -42
  15. package/test/ClipBoard.test.js +0 -105
  16. package/test/Credentials.test.js +0 -147
  17. package/test/Developer.test.js +0 -34
  18. package/test/Electron.test.js +0 -93
  19. package/test/Error.test.js +0 -16
  20. package/test/Exec.test.js +0 -25
  21. package/test/ExtensionHost.test.js +0 -127
  22. package/test/ExtensionHostColorTheme.test.js +0 -141
  23. package/test/ExtensionHostCommand.test.js +0 -27
  24. package/test/ExtensionHostCompletion.test.js +0 -45
  25. package/test/ExtensionHostDefinition.test.js +0 -35
  26. package/test/ExtensionHostDiagnostic.test.js +0 -23
  27. package/test/ExtensionHostFileSystem.test.js +0 -91
  28. package/test/ExtensionHostFormatting.test.js +0 -27
  29. package/test/ExtensionHostIconTheme.test.js +0 -73
  30. package/test/ExtensionHostLanguages.test.js +0 -212
  31. package/test/ExtensionHostOutput.test.js +0 -23
  32. package/test/ExtensionHostRename.test.js +0 -59
  33. package/test/ExtensionHostSemanticTokens.test.js +0 -26
  34. package/test/ExtensionHostTabCompletion.test.js +0 -35
  35. package/test/ExtensionHostTextDocument.test.js +0 -61
  36. package/test/ExtensionHostTypeDefinition.test.js +0 -35
  37. package/test/ExtensionHostWorkspace.test.js +0 -21
  38. package/test/ExtensionManagement.test.js +0 -408
  39. package/test/FileSystem.test.js +0 -294
  40. package/test/Json.test.js +0 -25
  41. package/test/Native.test.js +0 -31
  42. package/test/OutputChannel.test.js +0 -68
  43. package/test/Path.test.js +0 -17
  44. package/test/Platform.test.js +0 -61
  45. package/test/Preferences.test.js +0 -140
  46. package/test/Process.test.js +0 -9
  47. package/test/RgPath.test.js +0 -5
  48. package/test/Search.test.js +0 -45
  49. package/test/SearchFile.test.js +0 -80
  50. package/test/Terminal.test.js +0 -53
  51. package/test/Trash.test.js +0 -34
  52. package/test/WebSocketServer.test.js +0 -98
  53. package/test/fixture-search-1/index.html +0 -10
  54. package/test/fixture-search-file-1/fileA +0 -0
  55. package/test/fixture-search-file-1/fileB +0 -0
  56. package/test/fixture-search-file-1/nested/fileC +0 -0
@@ -1,408 +0,0 @@
1
- import { createReadStream, createWriteStream } from 'node:fs'
2
- import {
3
- access,
4
- mkdir,
5
- mkdtemp,
6
- readdir,
7
- readFile,
8
- rm,
9
- writeFile,
10
- } from 'node:fs/promises'
11
- import http from 'node:http'
12
- import { tmpdir } from 'node:os'
13
- import { dirname, join } from 'node:path'
14
- import { pipeline } from 'node:stream/promises'
15
- import { constants, createBrotliCompress } from 'node:zlib'
16
- import getPort from 'get-port'
17
- import { jest } from '@jest/globals'
18
- import tar from 'tar-fs'
19
- import VError from 'verror'
20
- import * as ExtensionManagement from '../src/parts/ExtensionManagement/ExtensionManagement.js'
21
- import * as Platform from '../src/parts/Platform/Platform.js'
22
-
23
- const getTmpDir = () => {
24
- return mkdtemp(join(tmpdir(), 'foo-'))
25
- }
26
-
27
- const exists = async (path) => {
28
- try {
29
- await access(path)
30
- return true
31
- } catch {
32
- return false
33
- }
34
- }
35
-
36
- /**
37
- * @param {string} inDir
38
- * @param {string} outFile
39
- */
40
- export const compress = async (inDir, outFile) => {
41
- await mkdir(dirname(outFile), { recursive: true })
42
- await pipeline(
43
- tar.pack(inDir),
44
- createBrotliCompress({
45
- params: {
46
- [constants.BROTLI_PARAM_QUALITY]: constants.BROTLI_MIN_QUALITY,
47
- },
48
- }),
49
- createWriteStream(outFile)
50
- )
51
- }
52
-
53
- const createExtensionTarBr = async (files) => {
54
- const folder = '/tmp/extension-test/test-author.test-extension'
55
- await rm(folder, { force: true, recursive: true })
56
- await mkdir(folder, { recursive: true })
57
- for (const [filePath, content] of Object.entries(files)) {
58
- await writeFile(`${folder}/${filePath}`, content)
59
- }
60
- await compress(folder, `${folder}.tar.br`)
61
- }
62
-
63
- let server
64
- let handler
65
-
66
- beforeAll(async () => {
67
- const port = await getPort()
68
- server = http.createServer((request, response) => {
69
- handler(request, response)
70
- })
71
- await new Promise((resolve) => {
72
- server.listen(port, () => {
73
- resolve(undefined)
74
- })
75
- })
76
- process.env.LVCE_MARKETPLACE_URL = `http://localhost:${port}`
77
- })
78
-
79
- afterAll(() => {
80
- server.close()
81
- })
82
-
83
- afterEach(() => {
84
- jest.restoreAllMocks()
85
- })
86
-
87
- // TODO this test is flaky sometimes: Jest has detected the following 1 open handle potentially keeping Jest from exiting: ● JSSTREAM
88
- test.skip('install', async () => {
89
- await createExtensionTarBr({
90
- 'extension.json': `{
91
- "id": "test-author.test-extension",
92
- "name": "test-extension",
93
- "publisher": "test-author",
94
- "version": "0.0.1",
95
- "main": "main.js"
96
- }
97
- `,
98
- 'main.js': 'export const activate = () => { console.info("hello world") }',
99
- 'package.json': '{ "type" : "module" }',
100
- })
101
- handler = async (request, response) => {
102
- switch (request.url) {
103
- case '/download/test-author.test-extension':
104
- response.statusCode = 200
105
- await pipeline(
106
- createReadStream(
107
- '/tmp/extension-test/test-author.test-extension.tar.br'
108
- ),
109
- response
110
- )
111
- break
112
- default:
113
- response.statusCode = 404
114
- response.end()
115
- break
116
- }
117
- }
118
- const tmpDir = await getTmpDir()
119
- Platform.state.getExtensionsPath = () => tmpDir
120
- await ExtensionManagement.install('test-author.test-extension')
121
- expect(
122
- await readFile(
123
- join(tmpDir, 'test-author.test-extension/extension.json'),
124
- 'utf-8'
125
- )
126
- ).toBe(`{
127
- "id": "test-author.test-extension",
128
- "name": "test-extension",
129
- "publisher": "test-author",
130
- "version": "0.0.1",
131
- "main": "main.js"
132
- }
133
- `)
134
- expect(
135
- await readFile(join(tmpDir, 'test-author.test-extension/main.js'), 'utf-8')
136
- ).toBe('export const activate = () => { console.info("hello world") }')
137
- expect(
138
- await readFile(
139
- join(tmpDir, 'test-author.test-extension/package.json'),
140
- 'utf-8'
141
- )
142
- ).toBe('{ "type" : "module" }')
143
- })
144
-
145
- test('install should fail when the server sends a bad status code', async () => {
146
- handler = (request, response) => {
147
- switch (request.url) {
148
- default:
149
- response.statusCode = 404
150
- return response.end()
151
- }
152
- }
153
- const tmpDir = await getTmpDir()
154
- Platform.state.getExtensionsPath = () => tmpDir
155
- await expect(
156
- ExtensionManagement.install('test-author.test-extension')
157
- ).rejects.toThrowError(
158
- /Failed to install extension "test-author.test-extension": Failed to download "http:\/\/localhost:\d+\/download\/test-author.test-extension": Response code 404 \(Not Found\)/
159
- )
160
- })
161
-
162
- test('install should fail when the server sends an invalid compressed object', async () => {
163
- // TODO avoid side effect in tests, use createServer
164
- handler = (request, res) => {
165
- switch (request.url) {
166
- case '/download/test-author.test-extension':
167
- res.statusCode = 200
168
- return res.end('abc')
169
- default:
170
- res.statusCode = 404
171
- return res.end()
172
- }
173
- }
174
- const tmpDir = await getTmpDir()
175
- Platform.state.getExtensionsPath = () => tmpDir
176
- await expect(
177
- ExtensionManagement.install('test-author.test-extension')
178
- ).rejects.toThrowError(
179
- /^Failed to install extension "test-author.test-extension": unexpected end of file/
180
- )
181
- })
182
-
183
- test('uninstall', async () => {
184
- const tmpDir = await getTmpDir()
185
- Platform.state.getExtensionsPath = () => tmpDir
186
- await mkdir(join(tmpDir, 'test-author.test-extension'))
187
- expect(await exists(join(tmpDir, 'test-author.test-extension'))).toBe(true)
188
- await ExtensionManagement.uninstall('test-author.test-extension')
189
- expect(await exists(join(tmpDir, 'test-author.test-extension'))).toBe(false)
190
- })
191
-
192
- test("uninstall should fail when extension doesn't exist", async () => {
193
- const tmpDir = await getTmpDir()
194
- Platform.state.getExtensionsPath = () => tmpDir
195
- await expect(
196
- ExtensionManagement.uninstall('test-author.test-extension')
197
- ).rejects.toThrowError(
198
- /^Failed to uninstall extension "test-author.test-extension": ENOENT: no such file or directory/
199
- )
200
- })
201
-
202
- // TODO test for extension main not found (extension host)
203
-
204
- // TODO test for extension json not found (extension host)
205
-
206
- // TODO test for extension code import fails (extension host)
207
- // TODO test for extension activation fails (in extension host)
208
- // TODO test for extension deactivation fails (in extension host)
209
- // TODO test for global unhandlederror/unhandledrejection (in extension host)
210
-
211
- test('getAllExtensions', async () => {
212
- const tmpDir1 = await getTmpDir()
213
- const manifestPath1 = join(tmpDir1, 'test-extension', 'extension.json')
214
- await mkdir(dirname(manifestPath1))
215
- await writeFile(manifestPath1, JSON.stringify({ id: 'test-extension' }))
216
- const tmpDir2 = await getTmpDir()
217
- const manifestPath2 = join(tmpDir2, 'builtin-extension', 'extension.json')
218
- await mkdir(dirname(manifestPath2))
219
- await writeFile(manifestPath2, JSON.stringify({ id: 'builtin-extension' }))
220
- const tmpDir3 = await getTmpDir()
221
- Platform.state.getExtensionsPath = () => tmpDir1
222
- Platform.state.getBuiltinExtensionsPath = () => tmpDir2
223
- Platform.state.getDisabledExtensionsPath = () => tmpDir3
224
- expect(await ExtensionManagement.getAllExtensions()).toEqual([
225
- {
226
- status: 'fulfilled',
227
- id: 'builtin-extension',
228
- path: join(tmpDir2, 'builtin-extension'),
229
- },
230
- {
231
- status: 'fulfilled',
232
- id: 'test-extension',
233
- path: join(tmpDir1, 'test-extension'),
234
- },
235
- ])
236
- })
237
-
238
- test('getAllExtensions - invalid extension.json', async () => {
239
- const spy = jest.spyOn(console, 'warn').mockImplementation(() => {})
240
- const tmpDir1 = await getTmpDir()
241
- const manifestPath = join(tmpDir1, 'test-extension', 'extension.json')
242
- await mkdir(dirname(manifestPath))
243
- await writeFile(manifestPath, '{invalid json}')
244
- const tmpDir2 = await getTmpDir()
245
- const tmpDir3 = await getTmpDir()
246
- Platform.state.getExtensionsPath = () => tmpDir1
247
- Platform.state.getBuiltinExtensionsPath = () => tmpDir2
248
- Platform.state.getDisabledExtensionsPath = () => tmpDir3
249
- expect(await ExtensionManagement.getAllExtensions()).toEqual([
250
- {
251
- path: join(tmpDir1, 'test-extension'),
252
- reason: new VError(
253
- 'Failed to load extension "test-extension": Failed to load extension manifest: JSON parsing error:'
254
- ),
255
- status: 'rejected',
256
- },
257
- ])
258
- })
259
-
260
- test('disable', async () => {
261
- const tmpDir1 = await getTmpDir()
262
- const tmpDir2 = await getTmpDir()
263
- await mkdir(join(tmpDir1, 'test-extension'))
264
- await writeFile(join(tmpDir1, 'test-extension', 'extension.json'), '{}')
265
- Platform.state.getExtensionsPath = () => tmpDir1
266
- Platform.state.getDisabledExtensionsPath = () => tmpDir2
267
- await ExtensionManagement.disable('test-extension')
268
- expect(await readdir(tmpDir1)).toEqual([])
269
- expect(await readdir(tmpDir2)).toEqual(['test-extension'])
270
- })
271
-
272
- test('disable should fail if enabled extension path does not exist', async () => {
273
- const tmpDir1 = await getTmpDir()
274
- const tmpDir2 = await getTmpDir()
275
- await mkdir(join(tmpDir1, 'test-extension'))
276
- await writeFile(join(tmpDir1, 'test-extension', 'extension.json'), '{}')
277
- Platform.state.getExtensionsPath = () => tmpDir1
278
- Platform.state.getDisabledExtensionsPath = () => tmpDir2
279
- const nonExistentPath1 = join(tmpDir1, 'non-existent-extension')
280
- const nonExistentPath2 = join(tmpDir2, 'non-existent-extension')
281
- await expect(
282
- ExtensionManagement.disable('non-existent-extension')
283
- ).rejects.toThrowError(
284
- `Failed to disable extension non-existent-extension: ENOENT: no such file or directory, rename '${nonExistentPath1}' -> '${nonExistentPath2}'`
285
- )
286
- })
287
-
288
- test('getExtensions - empty object', async () => {
289
- const tmpDir1 = await getTmpDir()
290
- const tmpDir2 = await getTmpDir()
291
- await mkdir(join(tmpDir1, 'test-extension-1'))
292
- await writeFile(join(tmpDir1, 'test-extension-1', 'extension.json'), '{}')
293
- Platform.state.getBuiltinExtensionsPath = () => tmpDir1
294
- Platform.state.getExtensionsPath = () => tmpDir2
295
- expect(await ExtensionManagement.getExtensions()).toEqual([
296
- {
297
- status: 'fulfilled',
298
- path: join(tmpDir1, '/test-extension-1'),
299
- },
300
- ])
301
- })
302
-
303
- test.skip('getExtensions - error - invalid value - empty array', async () => {
304
- const tmpDir1 = await getTmpDir()
305
- const tmpDir2 = await getTmpDir()
306
- await mkdir(join(tmpDir1, 'test-extension-1'))
307
- await writeFile(join(tmpDir1, 'test-extension-1', 'extension.json'), '[]')
308
- Platform.state.getBuiltinExtensionsPath = () => tmpDir1
309
- Platform.state.getExtensionsPath = () => tmpDir2
310
- expect(await ExtensionManagement.getExtensions()).toEqual([
311
- {
312
- status: 'fulfilled',
313
-
314
- path: join(tmpDir1, 'test-extension-1'),
315
- },
316
- ])
317
- })
318
-
319
- test('getExtensions - error - invalid value - null', async () => {
320
- const tmpDir1 = await getTmpDir()
321
- const tmpDir2 = await getTmpDir()
322
- await mkdir(join(tmpDir1, 'test-extension-1'))
323
- await writeFile(join(tmpDir1, 'test-extension-1', 'extension.json'), 'null')
324
- Platform.state.getBuiltinExtensionsPath = () => tmpDir1
325
- Platform.state.getExtensionsPath = () => tmpDir2
326
- expect(await ExtensionManagement.getExtensions()).toEqual([
327
- {
328
- status: 'rejected',
329
- reason: new VError(
330
- 'Failed to load extension "test-extension-1": Failed to load extension manifest: Invalid manifest file: Not an JSON object.'
331
- ),
332
- path: join(tmpDir1, 'test-extension-1'),
333
- },
334
- ])
335
- })
336
-
337
- test('getExtensions - error - invalid value - string', async () => {
338
- const tmpDir1 = await getTmpDir()
339
- const tmpDir2 = await getTmpDir()
340
- await mkdir(join(tmpDir1, 'test-extension-1'))
341
- await writeFile(join(tmpDir1, 'test-extension-1', 'extension.json'), '""')
342
- Platform.state.getBuiltinExtensionsPath = () => tmpDir1
343
- Platform.state.getExtensionsPath = () => tmpDir2
344
- expect(await ExtensionManagement.getExtensions()).toEqual([
345
- {
346
- status: 'rejected',
347
- reason: new VError(
348
- 'Failed to load extension "test-extension-1": Failed to load extension manifest: Invalid manifest file: Not an JSON object.'
349
- ),
350
- path: join(tmpDir1, 'test-extension-1'),
351
- },
352
- ])
353
- })
354
-
355
- test('getExtensions - error - invalid value - number', async () => {
356
- const tmpDir1 = await getTmpDir()
357
- const tmpDir2 = await getTmpDir()
358
- await mkdir(join(tmpDir1, 'test-extension-1'))
359
- await writeFile(join(tmpDir1, 'test-extension-1', 'extension.json'), '42')
360
- Platform.state.getBuiltinExtensionsPath = () => tmpDir1
361
- Platform.state.getExtensionsPath = () => tmpDir2
362
- expect(await ExtensionManagement.getExtensions()).toEqual([
363
- {
364
- status: 'rejected',
365
- reason: new VError(
366
- 'Failed to load extension "test-extension-1": Failed to load extension manifest: Invalid manifest file: Not an JSON object.'
367
- ),
368
- path: join(tmpDir1, 'test-extension-1'),
369
- },
370
- ])
371
- })
372
-
373
- test('getExtensions - error - invalid value - boolean', async () => {
374
- const tmpDir1 = await getTmpDir()
375
- const tmpDir2 = await getTmpDir()
376
- await mkdir(join(tmpDir1, 'test-extension-1'))
377
- await writeFile(join(tmpDir1, 'test-extension-1', 'extension.json'), 'true')
378
- Platform.state.getBuiltinExtensionsPath = () => tmpDir1
379
- Platform.state.getExtensionsPath = () => tmpDir2
380
- expect(await ExtensionManagement.getExtensions()).toEqual([
381
- {
382
- status: 'rejected',
383
- reason: new VError(
384
- 'Failed to load extension "test-extension-1": Failed to load extension manifest: Invalid manifest file: Not an JSON object.'
385
- ),
386
- path: join(tmpDir1, 'test-extension-1'),
387
- },
388
- ])
389
- })
390
-
391
- // TODO should have better error message here and also stack
392
- test('getExtensions - error - invalid json', async () => {
393
- const tmpDir1 = await getTmpDir()
394
- const tmpDir2 = await getTmpDir()
395
- await mkdir(join(tmpDir1, 'test-extension-1'))
396
- await writeFile(join(tmpDir1, 'test-extension-1', 'extension.json'), '{')
397
- Platform.state.getBuiltinExtensionsPath = () => tmpDir1
398
- Platform.state.getExtensionsPath = () => tmpDir2
399
- expect(await ExtensionManagement.getExtensions()).toEqual([
400
- {
401
- reason: new VError(
402
- 'Failed to load extension "test-extension-1": Failed to load extension manifest: Unexpected end of JSON input while parsing "{"'
403
- ),
404
- status: 'rejected',
405
- path: join(tmpDir1, 'test-extension-1'),
406
- },
407
- ])
408
- })
@@ -1,294 +0,0 @@
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
- })