feat: release OpsXShell 2.1.0 native Tauri edition
This commit is contained in:
1 parent
e9a0d21758
commit
a3dba0c6ed
311 files changed
+31748
-14897
No files matched your search
@@ -0,0 +1,50 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
const { listenMock } = vi.hoisted(() => ({
|
||||
listenMock: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@tauri-apps/api/event', () => ({
|
||||
listen: listenMock,
|
||||
}))
|
||||
|
||||
import { desktopApi } from '../../src/platform/desktop'
|
||||
|
||||
function deferred<T>() {
|
||||
let resolve!: (value: T) => void
|
||||
const promise = new Promise<T>((resolvePromise) => {
|
||||
resolve = resolvePromise
|
||||
})
|
||||
return { promise, resolve }
|
||||
}
|
||||
|
||||
describe('Tauri event subscriptions', () => {
|
||||
it('safely unregisters when React cleans up before listen resolves', async () => {
|
||||
const pending = deferred<() => void>()
|
||||
const unlisten = vi.fn()
|
||||
listenMock.mockReturnValueOnce(pending.promise)
|
||||
const listener = vi.fn()
|
||||
|
||||
desktopApi.onConnectionClosed(listener)
|
||||
desktopApi.removeListener('ssh:connection-closed', listener as (...args: unknown[]) => void)
|
||||
pending.resolve(unlisten)
|
||||
|
||||
await Promise.resolve()
|
||||
await Promise.resolve()
|
||||
|
||||
expect(unlisten).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('does not unregister an active listener more than once', async () => {
|
||||
const unlisten = vi.fn()
|
||||
listenMock.mockResolvedValueOnce(unlisten)
|
||||
const listener = vi.fn()
|
||||
|
||||
desktopApi.onConnectionClosed(listener)
|
||||
await Promise.resolve()
|
||||
desktopApi.removeListener('ssh:connection-closed', listener as (...args: unknown[]) => void)
|
||||
desktopApi.removeListener('ssh:connection-closed', listener as (...args: unknown[]) => void)
|
||||
|
||||
expect(unlisten).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,48 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import {
|
||||
downloadRemoteFile,
|
||||
localPath,
|
||||
readRemoteTextFile,
|
||||
remotePath,
|
||||
uploadRemoteFile,
|
||||
writeRemoteTextFile,
|
||||
} from '../../src/platform/sftp'
|
||||
|
||||
describe('SFTP path semantics', () => {
|
||||
beforeEach(() => vi.clearAllMocks())
|
||||
|
||||
it('always sends local then remote paths for upload', async () => {
|
||||
await uploadRemoteFile({
|
||||
sftpId: 'sftp-1',
|
||||
localPath: localPath('/Users/me/app.log'),
|
||||
remotePath: remotePath('/var/log/app.log'),
|
||||
})
|
||||
|
||||
expect(window.opsxApi.sftpUpload).toHaveBeenCalledWith('sftp-1', '/Users/me/app.log', '/var/log/app.log')
|
||||
})
|
||||
|
||||
it('always sends remote then local paths for download', async () => {
|
||||
await downloadRemoteFile({
|
||||
sftpId: 'sftp-1',
|
||||
remotePath: remotePath('/var/log/app.log'),
|
||||
localPath: localPath('/Users/me/app.log'),
|
||||
})
|
||||
|
||||
expect(window.opsxApi.sftpDownload).toHaveBeenCalledWith('sftp-1', '/var/log/app.log', '/Users/me/app.log')
|
||||
})
|
||||
|
||||
it('keeps remote editor reads and writes separate from transfers', async () => {
|
||||
await readRemoteTextFile({ sftpId: 'sftp-1', remotePath: remotePath('/etc/hosts') })
|
||||
await writeRemoteTextFile({
|
||||
sftpId: 'sftp-1',
|
||||
remotePath: remotePath('/etc/hosts'),
|
||||
content: '127.0.0.1 localhost',
|
||||
})
|
||||
|
||||
expect(window.opsxApi.sftpReadText).toHaveBeenCalledWith('sftp-1', '/etc/hosts')
|
||||
expect(window.opsxApi.sftpWriteText).toHaveBeenCalledWith('sftp-1', '/etc/hosts', '127.0.0.1 localhost')
|
||||
expect(window.opsxApi.sftpUpload).not.toHaveBeenCalled()
|
||||
expect(window.opsxApi.sftpDownload).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user