@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,42 @@
|
|
|
1
|
+
import { jest } from '@jest/globals'
|
|
2
|
+
import * as Callback from '../src/parts/Callback/Callback.js'
|
|
3
|
+
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
Callback.state.id = 0
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
test('register / resolve', () => {
|
|
9
|
+
const resolve = jest.fn()
|
|
10
|
+
const reject = jest.fn()
|
|
11
|
+
const id = Callback.register(resolve, reject)
|
|
12
|
+
Callback.resolve(id)
|
|
13
|
+
expect(resolve).toHaveBeenCalledTimes(1)
|
|
14
|
+
Callback.resolve(id)
|
|
15
|
+
expect(resolve).toHaveBeenCalledTimes(2)
|
|
16
|
+
Callback.unregister(id)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('register / resolve - nonexisting id', () => {
|
|
20
|
+
console.warn = jest.fn()
|
|
21
|
+
Callback.resolve(-1)
|
|
22
|
+
expect(console.warn).toHaveBeenCalledWith(
|
|
23
|
+
'callback -1 may already be disposed'
|
|
24
|
+
)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('register / reject', () => {
|
|
28
|
+
const resolve = jest.fn()
|
|
29
|
+
const reject = jest.fn()
|
|
30
|
+
const id = Callback.register(resolve, reject)
|
|
31
|
+
Callback.reject(id)
|
|
32
|
+
expect(reject).toHaveBeenCalledTimes(1)
|
|
33
|
+
Callback.unregister(id)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('register / reject - nonexisting id', () => {
|
|
37
|
+
console.warn = jest.fn()
|
|
38
|
+
Callback.reject(-1)
|
|
39
|
+
expect(console.warn).toHaveBeenCalledWith(
|
|
40
|
+
'callback (rejected) -1 may already be disposed'
|
|
41
|
+
)
|
|
42
|
+
})
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { jest } from '@jest/globals'
|
|
2
|
+
|
|
3
|
+
jest.unstable_mockModule('../src/parts/Exec/Exec.js', () => ({
|
|
4
|
+
exec: jest.fn(() => {
|
|
5
|
+
throw new Error('not implemented')
|
|
6
|
+
}),
|
|
7
|
+
}))
|
|
8
|
+
|
|
9
|
+
jest.unstable_mockModule('../src/parts/Platform/Platform.js', () => ({
|
|
10
|
+
getDesktop: jest.fn(() => {
|
|
11
|
+
throw new Error('not implemented')
|
|
12
|
+
}),
|
|
13
|
+
}))
|
|
14
|
+
|
|
15
|
+
const Exec = await import('../src/parts/Exec/Exec.js')
|
|
16
|
+
const Platform = await import('../src/parts/Platform/Platform.js')
|
|
17
|
+
const ClipBoard = await import('../src/parts/ClipBoard/ClipBoard.js')
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
jest.resetAllMocks()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test('readFiles - gnome - copied files', async () => {
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
Platform.getDesktop.mockImplementation(() => 'gnome')
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
Exec.exec.mockImplementation(() => {
|
|
28
|
+
return {
|
|
29
|
+
stdout: `copy
|
|
30
|
+
file:///test/my-folder`,
|
|
31
|
+
stderr: '',
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
expect(await ClipBoard.readFiles()).toEqual({
|
|
36
|
+
source: 'gnomeCopiedFiles',
|
|
37
|
+
type: 'copy',
|
|
38
|
+
files: ['/test/my-folder'],
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('readFiles - gnome - target not available', async () => {
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
Platform.getDesktop.mockImplementation(() => 'gnome')
|
|
45
|
+
// @ts-ignore
|
|
46
|
+
Exec.exec.mockImplementation(() => {
|
|
47
|
+
const error = new Error('command failed with exit code 1')
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
error.stderr = 'Error: target x-special/gnome-copied-files not available'
|
|
50
|
+
throw error
|
|
51
|
+
})
|
|
52
|
+
expect(await ClipBoard.readFiles()).toBe(undefined)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('writeFiles - gnome - copied files', async () => {
|
|
56
|
+
// @ts-ignore
|
|
57
|
+
Platform.getDesktop.mockImplementation(() => 'gnome')
|
|
58
|
+
// @ts-ignore
|
|
59
|
+
Exec.exec.mockImplementation(async () => {
|
|
60
|
+
return { stdout: '', stderr: '' }
|
|
61
|
+
})
|
|
62
|
+
await ClipBoard.writeFiles('copy', ['/test/my-folder'])
|
|
63
|
+
expect(Exec.exec).toHaveBeenCalledTimes(3)
|
|
64
|
+
expect(Exec.exec).toHaveBeenNthCalledWith(
|
|
65
|
+
1,
|
|
66
|
+
'xclip',
|
|
67
|
+
['-i', '-selection', 'clipboard', '-t', 'x-special/gnome-copied-files'],
|
|
68
|
+
{
|
|
69
|
+
input: `copy
|
|
70
|
+
file:///test/my-folder`,
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
expect(Exec.exec).toHaveBeenNthCalledWith(
|
|
74
|
+
2,
|
|
75
|
+
'xclip',
|
|
76
|
+
['-i', '-selection', 'clipboard', '-t', 'text/uri-list'],
|
|
77
|
+
{
|
|
78
|
+
input: 'file:///test/my-folder',
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
expect(Exec.exec).toHaveBeenNthCalledWith(
|
|
82
|
+
3,
|
|
83
|
+
'xclip',
|
|
84
|
+
['-i', '-selection', 'clipboard', '-t', 'text/plain'],
|
|
85
|
+
{
|
|
86
|
+
input: '/test/my-folder',
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
test('writeFiles - unsupported desktop', async () => {
|
|
92
|
+
// @ts-ignore
|
|
93
|
+
Platform.getDesktop.mockImplementation(() => 'test-desktop')
|
|
94
|
+
// @ts-ignore
|
|
95
|
+
Exec.exec.mockImplementation(async () => {
|
|
96
|
+
return { stdout: '', stderr: '' }
|
|
97
|
+
})
|
|
98
|
+
const consoleSpy = jest.spyOn(console, 'info')
|
|
99
|
+
await ClipBoard.writeFiles('copy', ['/test/my-folder'])
|
|
100
|
+
expect(Exec.exec).not.toHaveBeenCalled()
|
|
101
|
+
expect(consoleSpy).toHaveBeenCalledTimes(1)
|
|
102
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
103
|
+
'writing files to clipboard is not yet supported on test-desktop'
|
|
104
|
+
)
|
|
105
|
+
})
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { jest } from '@jest/globals'
|
|
2
|
+
|
|
3
|
+
// TODO actual keytar tests are failing in ci due to dbus error
|
|
4
|
+
// would be better to have tests using actual keytar
|
|
5
|
+
|
|
6
|
+
const serviceName = `Test 123`
|
|
7
|
+
|
|
8
|
+
jest.unstable_mockModule('keytar', () => {
|
|
9
|
+
return {
|
|
10
|
+
default: {
|
|
11
|
+
deletePassword: jest.fn(() => {
|
|
12
|
+
throw new Error('not implemented')
|
|
13
|
+
}),
|
|
14
|
+
findCredentials: jest.fn(() => {
|
|
15
|
+
throw new Error('not implemented')
|
|
16
|
+
}),
|
|
17
|
+
findPassword: jest.fn(() => {
|
|
18
|
+
throw new Error('not implemented')
|
|
19
|
+
}),
|
|
20
|
+
getPassword: jest.fn(() => {
|
|
21
|
+
throw new Error('not implemented')
|
|
22
|
+
}),
|
|
23
|
+
setPassword: jest.fn(() => {
|
|
24
|
+
throw new Error('not implemented')
|
|
25
|
+
}),
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const KeyTar = await import('keytar')
|
|
31
|
+
const Credentials = await import('../src/parts/Credentials/Credentials.js')
|
|
32
|
+
|
|
33
|
+
test('deletePassword', async () => {
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
KeyTar.default.deletePassword.mockImplementation(() => {})
|
|
36
|
+
await Credentials.deletePassword(serviceName, 'foo')
|
|
37
|
+
expect(KeyTar.default.deletePassword).toHaveBeenCalledTimes(1)
|
|
38
|
+
expect(KeyTar.default.deletePassword).toHaveBeenCalledWith(serviceName, 'foo')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('deletePassword - error', async () => {
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
KeyTar.default.deletePassword.mockImplementation(() => {
|
|
44
|
+
throw new Error('"dbus-launch" (No such file or directory)')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
await expect(
|
|
48
|
+
Credentials.deletePassword(serviceName, 'foo')
|
|
49
|
+
).rejects.toThrowError(
|
|
50
|
+
new Error(
|
|
51
|
+
`Failed to delete password from service ${serviceName}: "dbus-launch" (No such file or directory)`
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('findCredentials', async () => {
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
KeyTar.default.findCredentials.mockImplementation(() => {
|
|
59
|
+
return [{ account: 'abc', password: 'abc' }]
|
|
60
|
+
})
|
|
61
|
+
expect(await Credentials.findCredentials(serviceName)).toEqual([
|
|
62
|
+
{
|
|
63
|
+
account: 'abc',
|
|
64
|
+
password: 'abc',
|
|
65
|
+
},
|
|
66
|
+
])
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
test('findCredentials - error', async () => {
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
KeyTar.default.findCredentials.mockImplementation(() => {
|
|
72
|
+
throw new Error('"dbus-launch" (No such file or directory)')
|
|
73
|
+
})
|
|
74
|
+
await expect(Credentials.findCredentials(serviceName)).rejects.toThrowError(
|
|
75
|
+
new Error(
|
|
76
|
+
`Failed to find credentials from service ${serviceName}: "dbus-launch" (No such file or directory)`
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test('findPassword', async () => {
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
KeyTar.default.findPassword.mockImplementation(() => {
|
|
84
|
+
return 'bar'
|
|
85
|
+
})
|
|
86
|
+
expect(await Credentials.findPassword(serviceName)).toBe('bar')
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test('findPassword - error', async () => {
|
|
90
|
+
// @ts-ignore
|
|
91
|
+
KeyTar.default.findPassword.mockImplementation(() => {
|
|
92
|
+
throw new Error('"dbus-launch" (No such file or directory)')
|
|
93
|
+
})
|
|
94
|
+
await expect(Credentials.findPassword(serviceName)).rejects.toThrowError(
|
|
95
|
+
new Error(
|
|
96
|
+
`Failed to find password from service ${serviceName}: "dbus-launch" (No such file or directory)`
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
test('getPassword', async () => {
|
|
102
|
+
// @ts-ignore
|
|
103
|
+
KeyTar.default.getPassword.mockImplementation(() => {
|
|
104
|
+
return 'bar'
|
|
105
|
+
})
|
|
106
|
+
expect(await Credentials.getPassword(serviceName, 'foo')).toBe('bar')
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
test('getPassword - error', async () => {
|
|
110
|
+
// @ts-ignore
|
|
111
|
+
KeyTar.default.getPassword.mockImplementation(() => {
|
|
112
|
+
throw new Error('"dbus-launch" (No such file or directory)')
|
|
113
|
+
})
|
|
114
|
+
await expect(
|
|
115
|
+
Credentials.getPassword(serviceName, 'foo')
|
|
116
|
+
).rejects.toThrowError(
|
|
117
|
+
new Error(
|
|
118
|
+
`Failed to get password from service ${serviceName}: "dbus-launch" (No such file or directory)`
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('setPassword', async () => {
|
|
124
|
+
// @ts-ignore
|
|
125
|
+
KeyTar.default.setPassword.mockImplementation(() => {})
|
|
126
|
+
await Credentials.setPassword(serviceName, 'foo', 'bar')
|
|
127
|
+
expect(KeyTar.default.setPassword).toHaveBeenCalledTimes(1)
|
|
128
|
+
expect(KeyTar.default.setPassword).toHaveBeenCalledWith(
|
|
129
|
+
serviceName,
|
|
130
|
+
'foo',
|
|
131
|
+
'bar'
|
|
132
|
+
)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
test('setPassword - error', async () => {
|
|
136
|
+
// @ts-ignore
|
|
137
|
+
KeyTar.default.setPassword.mockImplementation(() => {
|
|
138
|
+
throw new Error('"dbus-launch" (No such file or directory)')
|
|
139
|
+
})
|
|
140
|
+
await expect(
|
|
141
|
+
Credentials.setPassword(serviceName, 'foo', 'bar')
|
|
142
|
+
).rejects.toThrowError(
|
|
143
|
+
new Error(
|
|
144
|
+
`Failed to set password for service ${serviceName}: "dbus-launch" (No such file or directory)`
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { access } from 'node:fs/promises'
|
|
2
|
+
import { jest } from '@jest/globals'
|
|
3
|
+
import * as Developer from '../src/parts/Developer/Developer.js'
|
|
4
|
+
|
|
5
|
+
const exists = async (path) => {
|
|
6
|
+
try {
|
|
7
|
+
await access(path)
|
|
8
|
+
return true
|
|
9
|
+
} catch {
|
|
10
|
+
return false
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
test.skip('createHeapSnapshot', async () => {
|
|
15
|
+
Date.now = () => 123456
|
|
16
|
+
// TODO jest esm mock not working https://github.com/facebook/jest/issues/10025
|
|
17
|
+
jest.mock('v8', () => ({
|
|
18
|
+
getHeapSnapshot() {
|
|
19
|
+
return ''
|
|
20
|
+
},
|
|
21
|
+
}))
|
|
22
|
+
await Developer.createHeapSnapshot()
|
|
23
|
+
expect(await exists('/tmp/vscode-123456.heapsnapshot')).toBe(true)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('sharedProcessMemoryUsage', () => {
|
|
27
|
+
expect(Developer.sharedProcessMemoryUsage()).toEqual({
|
|
28
|
+
arrayBuffers: expect.any(Number),
|
|
29
|
+
external: expect.any(Number),
|
|
30
|
+
heapTotal: expect.any(Number),
|
|
31
|
+
heapUsed: expect.any(Number),
|
|
32
|
+
rss: expect.any(Number),
|
|
33
|
+
})
|
|
34
|
+
})
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { jest } from '@jest/globals'
|
|
2
|
+
import * as Electron from '../src/parts/Electron/Electron.js'
|
|
3
|
+
|
|
4
|
+
test('toggleDevtools', () => {
|
|
5
|
+
Electron.state.send = jest.fn()
|
|
6
|
+
Electron.toggleDevtools()
|
|
7
|
+
expect(Electron.state.send).toHaveBeenCalledWith({
|
|
8
|
+
jsonrpc: '2.0',
|
|
9
|
+
method: 6523,
|
|
10
|
+
params: [],
|
|
11
|
+
})
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('windowMinimize', () => {
|
|
15
|
+
Electron.state.send = jest.fn()
|
|
16
|
+
Electron.windowMinimize()
|
|
17
|
+
expect(Electron.state.send).toHaveBeenCalledWith({
|
|
18
|
+
jsonrpc: '2.0',
|
|
19
|
+
method: 6521,
|
|
20
|
+
params: [],
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('windowMaximize', () => {
|
|
25
|
+
Electron.state.send = jest.fn()
|
|
26
|
+
Electron.windowMaximize()
|
|
27
|
+
expect(Electron.state.send).toHaveBeenCalledWith({
|
|
28
|
+
jsonrpc: '2.0',
|
|
29
|
+
method: 6522,
|
|
30
|
+
params: [],
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('windowUnmaximize', () => {
|
|
35
|
+
Electron.state.send = jest.fn()
|
|
36
|
+
Electron.windowUnmaximize()
|
|
37
|
+
expect(Electron.state.send).toHaveBeenCalledWith({
|
|
38
|
+
jsonrpc: '2.0',
|
|
39
|
+
method: 6524,
|
|
40
|
+
params: [],
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('windowClose', () => {
|
|
45
|
+
Electron.state.send = jest.fn()
|
|
46
|
+
Electron.windowClose()
|
|
47
|
+
expect(Electron.state.send).toBeCalledWith({
|
|
48
|
+
jsonrpc: '2.0',
|
|
49
|
+
method: 6525,
|
|
50
|
+
params: [],
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('windowReload', () => {
|
|
55
|
+
Electron.state.send = jest.fn()
|
|
56
|
+
Electron.windowReload()
|
|
57
|
+
expect(Electron.state.send).toBeCalledWith({
|
|
58
|
+
jsonrpc: '2.0',
|
|
59
|
+
method: 6526,
|
|
60
|
+
params: [],
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('about', () => {
|
|
65
|
+
Electron.state.send = jest.fn()
|
|
66
|
+
Electron.about()
|
|
67
|
+
expect(Electron.state.send).toBeCalledWith({
|
|
68
|
+
jsonrpc: '2.0',
|
|
69
|
+
method: 20001,
|
|
70
|
+
params: [],
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
test('showOpenDialog', () => {
|
|
75
|
+
Electron.state.send = jest.fn()
|
|
76
|
+
Electron.showOpenDialog()
|
|
77
|
+
expect(Electron.state.send).toBeCalledWith({
|
|
78
|
+
jsonrpc: '2.0',
|
|
79
|
+
method: 20100,
|
|
80
|
+
params: [],
|
|
81
|
+
id: expect.any(Number),
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('crashMainProcess', () => {
|
|
86
|
+
Electron.state.send = jest.fn()
|
|
87
|
+
Electron.crashMainProcess()
|
|
88
|
+
expect(Electron.state.send).toBeCalledWith({
|
|
89
|
+
jsonrpc: '2.0',
|
|
90
|
+
method: 7723,
|
|
91
|
+
params: [],
|
|
92
|
+
})
|
|
93
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as Error from '../src/parts/Error/Error.js'
|
|
2
|
+
|
|
3
|
+
// TODO don't shim global Error object
|
|
4
|
+
|
|
5
|
+
// TODO
|
|
6
|
+
test('OperationalError', () => {
|
|
7
|
+
const error = globalThis.Error('enoent: no such file')
|
|
8
|
+
const operationalError = new Error.OperationalError({
|
|
9
|
+
cause: error,
|
|
10
|
+
code: 'E_FAILED_TO_READ_FILE',
|
|
11
|
+
message: 'Failed to read file',
|
|
12
|
+
})
|
|
13
|
+
expect(operationalError.toString()).toBe(
|
|
14
|
+
'OperationalError: Failed to read file: enoent: no such file'
|
|
15
|
+
)
|
|
16
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as Exec from '../src/parts/Exec/Exec.js'
|
|
2
|
+
|
|
3
|
+
test('exec - stdout', async () => {
|
|
4
|
+
expect(
|
|
5
|
+
await Exec.exec('node', ['-e', "process.stdout.write('a')"], {})
|
|
6
|
+
).toEqual({
|
|
7
|
+
stderr: '',
|
|
8
|
+
stdout: 'a',
|
|
9
|
+
})
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('exec - stderr', async () => {
|
|
13
|
+
expect(
|
|
14
|
+
await Exec.exec('node', ['-e', "process.stderr.write('b')"], {})
|
|
15
|
+
).toEqual({
|
|
16
|
+
stderr: 'b',
|
|
17
|
+
stdout: '',
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('exec - error', async () => {
|
|
22
|
+
await expect(Exec.exec('node', ['-e', 'oops'], {})).rejects.toThrowError(
|
|
23
|
+
'Command failed with exit code 1: node -e oops'
|
|
24
|
+
)
|
|
25
|
+
})
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { mkdir, mkdtemp, writeFile } from 'node:fs/promises'
|
|
2
|
+
import { tmpdir } from 'node:os'
|
|
3
|
+
import { join } from 'node:path'
|
|
4
|
+
import * as ExtensionHost from '../src/parts/ExtensionHost/ExtensionHost.js'
|
|
5
|
+
import * as ExtensionManagement from '../src/parts/ExtensionManagement/ExtensionManagement.js'
|
|
6
|
+
import * as Platform from '../src/parts/Platform/Platform.js'
|
|
7
|
+
|
|
8
|
+
const getTmpDir = () => {
|
|
9
|
+
return mkdtemp(join(tmpdir(), 'foo-'))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
test.skip('start / stop', async () => {
|
|
13
|
+
await ExtensionHost.start()
|
|
14
|
+
ExtensionHost.stop()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
// TODO test with mock extensions
|
|
18
|
+
test.skip('activateAll', async () => {
|
|
19
|
+
const tmpDir1 = await getTmpDir()
|
|
20
|
+
const tmpDir2 = await getTmpDir()
|
|
21
|
+
ExtensionManagement.state.builtinExtensionsPath = tmpDir1
|
|
22
|
+
ExtensionManagement.state.extensionPath = tmpDir2
|
|
23
|
+
await ExtensionHost.start()
|
|
24
|
+
await ExtensionHost.activateAll()
|
|
25
|
+
await ExtensionHost.stop()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('start - error - path not found', async () => {
|
|
29
|
+
Platform.state.getExtensionHostPath = () => {
|
|
30
|
+
return '/test'
|
|
31
|
+
}
|
|
32
|
+
const socket = {
|
|
33
|
+
on() {},
|
|
34
|
+
}
|
|
35
|
+
await expect(ExtensionHost.start(socket)).rejects.toThrowError(
|
|
36
|
+
new Error(
|
|
37
|
+
'Failed to start extension host: Extension Host exited with code 1'
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('start - error - path is a directory', async () => {
|
|
43
|
+
const tmpDir = await getTmpDir()
|
|
44
|
+
Platform.state.getExtensionHostPath = () => {
|
|
45
|
+
return tmpDir
|
|
46
|
+
}
|
|
47
|
+
const socket = {
|
|
48
|
+
on() {},
|
|
49
|
+
}
|
|
50
|
+
await mkdir(tmpDir, { recursive: true })
|
|
51
|
+
// TODO error message should include stderr of extension host
|
|
52
|
+
await expect(ExtensionHost.start(socket)).rejects.toThrowError(
|
|
53
|
+
new Error(
|
|
54
|
+
'Failed to start extension host: Extension Host exited with code 1'
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('start - error - syntax error', async () => {
|
|
60
|
+
const tmpDir = await getTmpDir()
|
|
61
|
+
const extensionHostPath = join(tmpDir, 'extensionHost.js')
|
|
62
|
+
await writeFile(extensionHostPath, '...')
|
|
63
|
+
Platform.state.getExtensionHostPath = () => {
|
|
64
|
+
return extensionHostPath
|
|
65
|
+
}
|
|
66
|
+
const socket = {
|
|
67
|
+
on() {},
|
|
68
|
+
}
|
|
69
|
+
// TODO error message should include stderr of extension host: SyntaxError: Unexpected end of input
|
|
70
|
+
await expect(ExtensionHost.start(socket)).rejects.toThrowError(
|
|
71
|
+
new Error(
|
|
72
|
+
'Failed to start extension host: Extension Host exited with code 1'
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('start - error - uncaught exception', async () => {
|
|
78
|
+
const tmpDir = await getTmpDir()
|
|
79
|
+
const extensionHostPath = join(tmpDir, 'extensionHost.js')
|
|
80
|
+
await writeFile(extensionHostPath, "throw new Error('oops')")
|
|
81
|
+
Platform.state.getExtensionHostPath = () => {
|
|
82
|
+
return extensionHostPath
|
|
83
|
+
}
|
|
84
|
+
const socket = {
|
|
85
|
+
on() {},
|
|
86
|
+
}
|
|
87
|
+
// TODO error message should include stderr of extension host: SyntaxError: Unexpected end of input
|
|
88
|
+
await expect(ExtensionHost.start(socket)).rejects.toThrowError(
|
|
89
|
+
new Error(
|
|
90
|
+
'Failed to start extension host: Extension Host exited with code 1'
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('start - error - custom exit code', async () => {
|
|
96
|
+
const tmpDir = await getTmpDir()
|
|
97
|
+
const extensionHostPath = join(tmpDir, 'extensionHost.js')
|
|
98
|
+
await writeFile(extensionHostPath, 'process.exit(123)')
|
|
99
|
+
Platform.state.getExtensionHostPath = () => {
|
|
100
|
+
return extensionHostPath
|
|
101
|
+
}
|
|
102
|
+
const socket = {
|
|
103
|
+
on() {},
|
|
104
|
+
}
|
|
105
|
+
await expect(ExtensionHost.start(socket)).rejects.toThrowError(
|
|
106
|
+
new Error(
|
|
107
|
+
'Failed to start extension host: Extension Host exited with code 123'
|
|
108
|
+
)
|
|
109
|
+
)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
test('start - child process should be closed when socket immediately is closed', async () => {
|
|
113
|
+
const tmpDir = await getTmpDir()
|
|
114
|
+
const extensionHostPath = join(tmpDir, 'extensionHost.js')
|
|
115
|
+
await writeFile(extensionHostPath, 'process.on(`message`, ()=>{})')
|
|
116
|
+
Platform.state.getExtensionHostPath = () => {
|
|
117
|
+
return extensionHostPath
|
|
118
|
+
}
|
|
119
|
+
const socket = {
|
|
120
|
+
on(event, listener) {
|
|
121
|
+
if (event === 'close') {
|
|
122
|
+
listener()
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
}
|
|
126
|
+
await ExtensionHost.start(socket)
|
|
127
|
+
})
|