SFTP
Reaches Driver8's SFTP capability the same way as Kafka: a WebDriver session with
browserName: "pn5-driver8", then plain REST commands relative to that session, under the pn5-sftp/* path prefix.
File contents travel base64-encoded in the JSON body.
Status: this package's own CI runs the SFTP tests end to end against a real Driver8 and an SFTP server started by the pipeline: listing, upload and download (text and binary, byte for byte), overwriting, creating and removing a directory, and the error for a missing file. The implementation follows the Java client's
RemoteSftpAgent.
Usage
import { test, expect } from '@pumpo5.dev/core'
test('lists a remote directory', async ({ sftp }) => {
const entries = await sftp.list('.')
expect(Array.isArray(entries)).toBe(true)
})
The sftp fixture creates a Driver8 session before the test and closes it after, whether the test passes or fails.
Connection configuration
The sftp fixture resolves its connection details from a named profile, defaulting to SFTP. For the default
profile, values are looked up as, in order of precedence:
config.conf, under the dotted key derived from the profile name (SFTP→sftp):sftp.host="my-sftp-server"
sftp.username="myUsername"
sftp.password="myPassword"
sftp.port=22- Environment variables named
<PROFILE>_<SUFFIX>, e.g.SFTP_HOST,SFTP_USERNAME,SFTP_PASSWORD,SFTP_PORT.
host, username, password and port are all required, and port must be an integer: the fixture throws with a
descriptive error naming both possible sources if any is missing. These map directly onto the Java client's
pn5:sftpHost, pn5:sftpUsername, pn5:sftpPassword and pn5:sftpPort capabilities (see
SFTP capabilities reference).
Set sftp.hidePassword=true (or SFTP_HIDEPASSWORD=true) to send the password as pn5:hidden:sftpPassword, so it is
masked in the farm's logs.
Using a different profile
Same mechanism as Kafka - override with test.use({ sftpProfile: '...' }) to read a different named profile's
config.conf/environment variables in a given test or describe block. See the equivalent section on the
Kafka page for the pattern and the caveat about
file-level test.skip() only checking the default profile.
Method reference
sftp.download(remotePath)
Returns a Buffer with the file's decoded contents.
import * as fs from 'fs/promises'
test('downloads a generated report', async ({ sftp }) => {
const contents = await sftp.download('/reports/latest.csv')
expect(contents.toString('utf-8')).toContain('orderId')
// Save it locally if the test needs to inspect it further, e.g. with a CSV parser:
await fs.writeFile('report.csv', contents)
})
sftp.upload(remotePath, contents)
contents is a Buffer or string; encoded to base64 before sending.
import * as fs from 'fs/promises'
test('uploads a test input file as a string', async ({ sftp }) => {
await sftp.upload('/incoming/test-input.csv', 'orderId,status\n123,CREATED\n')
// Each entry of list() is a line of the server's long listing, so match on part of it.
const entries = await sftp.list('/incoming')
expect(entries.some(entry => entry.includes('test-input.csv'))).toBe(true)
})
test('uploads a local file as a Buffer', async ({ sftp }) => {
const fileContents = await fs.readFile('fixtures/sample.pdf')
await sftp.upload('/incoming/sample.pdf', fileContents)
})
sftp.list(remotePath)
Returns string[], the entries in the remote directory. Each entry is one line of the server's long listing format
(permissions, owner, size, date and name), not a bare file name, so check for a file with
entries.some(entry => entry.includes(name)) rather than toContain(name).
sftp.lstat(remotePath)
Returns the file attributes as a string (the Java SftpATTRS text), for example one that starts with d for a
directory.
expect((await sftp.lstat('/incoming/archive')).startsWith('d')).toBe(true)
sftp.makeDirectory(remotePath)
sftp.rename(oldRemotePath, newRemotePath)
sftp.remove(remotePath)
Removes a file.
sftp.removeDirectory(remotePath)
sftp.close()
Closes the Driver8 session. Called automatically by the fixture after the test; only call this yourself if you
created an SftpAgent directly instead of using the fixture.