File System

The file system plugin allows you to easily manage files and directories during tests and write assertions against them. You can install the plugin from the npm packages registry as follows.

npm i -D @japa/file-system@1.1.0

The next step is registering the plugin inside the plugins array.

import { fileSystem } from '@japa/file-system'
import { configure, processCliArgs } from '@japa/runner'
configure({
...processCliArgs(process.argv.slice(2)),
...{
files: ['tests/**/*.spec.js'],
plugins: [fileSystem()]
}
})
const { fileSystem } = require('@japa/file-system')
const { configure, processCliArgs } = require('@japa/runner')
configure({
...processCliArgs(process.argv.slice(2)),
...{
files: ['tests/**/*.spec.js'],
plugins: [fileSystem()]
}
})

Basic usage

Once the plugin has been registered, you can access the fs property from the test context. The fs property exposes the helper functions to read and write files. For example:

test('read rc file', async ({ fs }) => {
await fs.write('rc.json', JSON.stringify({
foo: 'bar'
}))
await runMethodThatNeedsRcFile()
})

A few things are happening here.

  • First, you do not have to construct absolute paths to write the file. The file system plugin writes the files inside your operating system's tmp directory.
  • You do not have to clean up any files or directories. The filesystem plugin will automatically perform the clean up after the test finishes.

You can specify a custom base directory or turn off the auto cleaning of files using the following configuration options.

{
plugins: [
fileSystem({
basePath: join(__dirname, './tmp'),
autoClean: false,
})
]
}

Assertions

The filesystem plugin extends the assert module and adds the following assertion methods to test file system operations quickly. All file system assertion methods are asynchronous.

fileExists/dirExists

Assert a file or a directory exists at a given location.

test('make controller', ({ assert, fs }) => {
await makeController(fs.basePath, 'users')
await assert.fileExists('controllers/users_controller.ts')
})
ArgumentType
filePathString

fileNotExists/dirNotExists

Assert a file or a directory should not exist at a given location.

test('make controller', ({ assert, fs }) => {
await makeController(fs.basePath, 'users', { dryRun: true })
await assert.fileNotExists('controllers/users_controller.ts')
})
ArgumentType
filePathString

fileEquals

Assert the contents of the file against a string value.

test('make controller', ({ assert, fs }) => {
await makeController(fs.basePath, 'users')
await assert.fileEquals('controllers/users_controller.ts', `
export default class UsersController {}
`)
})
ArgumentType
filePathString
contentsString

fileContains

Assert the file contents to contain a substring or match a regular expression.

test('make controller', ({ assert, fs }) => {
await makeController(fs.basePath, 'users')
await assert.fileContains(
'controllers/users_controller.ts',
'class UsersController'
)
await assert.fileContains(
'controllers/users_controller.ts',
/class UsersController/
)
})
ArgumentType
filePathString
substringString | Regexp

fileSameAs

Assert the contents of the file matches the contents of another file.

test('make controller', ({ assert, fs }) => {
await makeController(fs.basePath, 'users')
await assert.fileSameAs(
'controllers/users_controller.ts',
'stubs/controller/make'
)
})
ArgumentType
filePathString
otherFilePathString

fileIsEmpty

Assert the file exists and is empty or has only whitespaces.

test('make preload file', ({ assert, fs }) => {
await makePreloadFile(fs.basePath, 'routes')
await assert.fileIsEmpty('start/routes.ts')
})
ArgumentType
filePathString

fileIsNotEmpty

Assert the file exists and is not empty.

test('make routes file', ({ assert, fs }) => {
await makeRoutesFile(fs.basePath)
await assert.fileIsNotEmpty('start/routes.ts')
})
ArgumentType
filePathString

hasFiles

Assert the root of the filesystem has all the mentioned files.

test('copy stubs', ({ assert, fs }) => {
await copyStubs(fs.basePath)
await assert.hasFiles([
'make/controller/main.stub',
'make/event/main.stub',
'make/listener/main.stub',
'make/command/main.stub',
])
})
ArgumentType
filesString[]

doesNotHaveFiles

Assert the filesystem's root does not have any of the mentioned files.

test('copy stubs', ({ assert, fs }) => {
await copyStubs(fs.basePath, { dryRun: true })
await assert.doesNotHaveFiles([
'make/controller/main.stub',
'make/event/main.stub',
'make/listener/main.stub',
'make/command/main.stub',
])
})
ArgumentType
filesString[]

dirIsEmpty

Assert a given directory is empty.

test('copy stubs', ({ assert, fs }) => {
await copyStubs(fs.basePath, { dryRun: true })
await assert.dirIsEmpty('make')
})
ArgumentType
dirPathString?

dirIsNotEmpty

Assert a given directory is not empty.

test('copy stubs', ({ assert, fs }) => {
await copyStubs(fs.basePath)
await assert.dirIsNotEmpty('make')
})
ArgumentType
dirPathString?

File system API

Following is the list of methods available on the ctx.fs property. All methods accept relative paths.

cleanup

Remove the file system root directory. If you have turned off autoClean, you might want to use this method as a hook to clean up files after each test.

test.group('Make files', (group) => {
group.each.setup(({ context }) => {
return () => context.fs.cleanup()
})
})

create

Create a file at a given location. The missing directories will be created automatically.

test('write rc file', async ({ fs }) => {
await fs.write('rc.json', JSON.stringify({
foo: 'bar'
}))
})
ArgumentType
filePathString
contentsString
optionsWriteFileOptions

createJson

Same as create, but writes the contents as JSON.

test('read rc file', async ({ fs }) => {
await fs.createJson('rc.json', {
foo: 'bar'
})
})
ArgumentType
filePathString
contentsObject
optionsJsonOutputOptions

remove

Remove a file or a directory by its location.

test('delete rc file', async ({ fs }) => {
await fs.remove('rc.json')
})
ArgumentType
filePathString

rootExists

Check if the root directory of the file system exists. The method returns a boolean value.

test.group('Make files', (group) => {
group.each.setup(({ context }) => {
return async () => {
if (await context.fs.rootExists()) {
await context.fs.cleanup()
}
}
})
})

exists

Check if a directory exists. The method returns a boolean value.

test('do not update rc file', async ({ fs }) => {
if (await fs.exists('rc.json')) {
await fs.create('rc.json', contents)
}
})
ArgumentType
filePathString

contents

Returns the contents of a file as a string

test('read rc file', async ({ fs }) => {
const contents = await fs.contents('rc.json')
})
ArgumentType
filePathString

contentsJson

Parse the contents of a file as JSON and return it as an object.

test('read package.json file', async ({ fs }) => {
const contents = await fs.contentsJson('package.json')
console.log(contents.devDependencies)
})

stats

Get fs.Stats for a file by its location.

test('read rc file', async ({ fs }) => {
const stats = await fs.stats('rc.json')
})
ArgumentType
filePathString

readDir

Get an array of files for a directory. The return value is an array of EntryInfo objects.

test('copy files', async ({ fs }) => {
const entries = await fs.readDir('make')
entries.forEach((entry) => {
console.log(entry.path)
console.log(entry.fullPath)
console.log(entry.basename)
console.log(entry.stats)
})
})
ArgumentType
filePathString

adapter

The adapter property is a reference to the fs-extra package, and you can use it to perform file system operations not covered by the FileSystem class.

test('copy files', async ({ fs }) => {
await fs.adapter.move(source, destination)
})