Skip to main content

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:

  1. 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
  2. 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.