# temp-context

> Test Context To Initialise Temporary Directory For Each Test, And Remove It At The End. It Contains Methods To Read, Write, Clone, Assert Existence And Remove Files Inside And Outside Of Temp Dir.

Latest version **2.2.0** (published 2020-04-07) · AGPL-3.0 license · 0 weekly downloads

## Install

```sh
npm install temp-context
pnpm add temp-context
yarn add temp-context
bun add temp-context
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 2.2.0 |
| Published | 2020-04-07 |
| First published | 2018-09-15 |
| Weekly downloads | 0 |
| License | AGPL-3.0 |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 0 |
| Unpacked size | 89.5 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Anton |
| Maintainers | zvr |
| Keywords | temp-context, wrote, temp, filesystem, fs, remove, setup, teardown, before, after, beforeEach, afterEach |

## Links

- npm: https://www.npmjs.com/package/temp-context
- Repository: https://gitlab.com/wrote/temp-context
- Homepage: https://www.contexttesting.com/
- Issues: https://gitlab.com/artdeco/issues/-/issues/
- npm.io page: https://npm.io/package/temp-context

## Alternatives

- [unionfs](https://npm.io/package/unionfs.md) — 2.2M weekly downloads
- [path-starts-with](https://npm.io/package/path-starts-with.md) — 35.9K weekly downloads
- [redzip](https://npm.io/package/redzip.md) — 1.2K weekly downloads
- [vscode-anymatch](https://npm.io/package/vscode-anymatch.md) — 848 weekly downloads
- [@ledgerhq/coin-filecoin](https://npm.io/package/@ledgerhq/coin-filecoin.md) — 793 weekly downloads

## Recent versions

- 2.2.0 (latest) — 2020-04-07
- 2.1.3 — 2019-04-04
- 2.1.2 — 2019-03-30
- 2.1.1 — 2019-03-27
- 2.1.0 — 2019-01-08
- 2.0.0 — 2018-09-28
- 1.3.0 — 2018-09-27
- 1.2.0 — 2018-09-27
- 1.1.0 — 2018-09-20
- 1.0.0 — 2018-09-15

## README

<div align="center">

# temp-context

[![npm version](https://badge.fury.io/js/temp-context.svg)](https://www.npmjs.com/package/temp-context)
<a href="https://gitlab.com/artdeco/wrote/temp-context/-/commits/master">
  <img src="https://gitlab.com/artdeco/wrote/temp-context/badges/master/pipeline.svg"
    alt="Pipeline Badge">
</a>

`temp-context` is a [_Zoroaster_](https://github.com/artdecocode/zoroaster) test context to initialise a temporary directory for each test, and remove it at the end. It also contains methods to read, write, clone, assert existence and remove files inside and outside of the temp dir.
</div>

```sh
yarn add -E temp-context
```

<div align="center"><a href="#table-of-contents">
  <img src="/.documentary/section-breaks/0.svg?sanitize=true">
</a></div>

## Table Of Contents

- [Table Of Contents](#table-of-contents)
- [API](#api)
- [**class `TempContext`**](#class-tempcontext)
  * [`TempContext`](#type-tempcontext)
  * [`SnapshotOptions`](#type-snapshotoptions)
- [**Example**](#example)
  * [Masks](#masks)
  * [Specs](#specs)
  * [Output](#output)
  * [Autocompletion](#autocompletion)
- [**Extending**](#extending)
- [Copyright](#copyright)

<div align="center"><a href="#table-of-contents">
  <img src="/.documentary/section-breaks/1.svg?sanitize=true">
</a></div>

## API

The package is available by importing its default function:

```js
import TempContext from 'temp-context'
```

<div align="center"><a href="#table-of-contents">
  <img src="/.documentary/section-breaks/2.svg?sanitize=true">
</a></div>

## **class `TempContext`**

Instances of this test context class will create a `temp` directory in the `test` folder on initialisation, and remove it at the end of each test. To change the location of the test directory, [extend the class](#extending).

The test context is used with the _Zoroaster_ testing framework, which will initialise and destroy it for every test. Check the [example](#example) section to see how tests are implemented.

__<a name="type-tempcontext">`TempContext`</a>__: A test context that creates and destroys a temp directory. By default, the temp directory will be `test/temp` relative to the current working directory, but it can be changed by extending the class and setting its `TEMP` property in the constructor.
<table>
 <thead><tr>
  <th>Name</th>
  <th>Type &amp; Description</th>
 </tr></thead>
 <tr>
  <td rowSpan="3" align="center"><ins>constructor</ins></td>
  <td><em>new () => <a href="#type-tempcontext" title="A test context that creates and destroys a temp directory. By default, the temp directory will be `test/temp` relative to the current working directory, but it can be changed by extending the class and setting its `TEMP` property in the constructor.">TempContext</a></em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   The constructor method will be called by a context-testing framework automatically.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>TEMP</ins></td>
  <td><em>string</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   The path to the temp directory.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>_useOSTemp</ins></td>
  <td><em>(name: string) => void</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   This method should be called in the constructor by classes that extend the <code>TempContext</code> to use the temp directory of the os system.<br/>
   <kbd><strong>name*</strong></kbd> <em><code>string</code></em>: The name of the directory inside of the temp dir.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>readGlobal</ins></td>
  <td><em>(path: string) => !Promise&lt;string&gt;</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Read a file from the filesystem.<br/>
   <kbd><strong>path*</strong></kbd> <em><code>string</code></em>: Path of the file to read.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>existsGlobal</ins></td>
  <td><em>(path: string) => !Promise&lt;boolean&gt;</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Check if the path exists on the filesystem.<br/>
   <kbd><strong>path*</strong></kbd> <em><code>string</code></em>: The path to check.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>exists</ins></td>
  <td><em>(path: string) => !Promise&lt;boolean&gt;</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Check if the path exists in the temp directory.<br/>
   <kbd><strong>path*</strong></kbd> <em><code>string</code></em>: The relative path inside of the temp dir to check.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>read</ins></td>
  <td><em>(path: string) => !Promise&lt;string&gt;</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Read a file inside of the temp directory.<br/>
   <kbd><strong>path*</strong></kbd> <em><code>string</code></em>: The path to the file in the temp directory.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>write</ins></td>
  <td><em>(path: string, data: (string | !Buffer)) => !Promise&lt;string&gt;</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Write a file in the temp directory.<br/>
   <kbd><strong>path*</strong></kbd> <em><code>string</code></em>: The path to the file within the temp directory.<br/>
   <kbd><strong>data*</strong></kbd> <em><code>(string \| !Buffer)</code></em>: The data to write.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>resolve</ins></td>
  <td><em>(path: string) => string</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Get a path to a file inside of the temp directory.<br/>
   <kbd><strong>path*</strong></kbd> <em><code>string</code></em>: The relative path to the file inside of the temp dir.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>rm</ins></td>
  <td><em>(path: string) => !Promise&lt;void&gt;</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Remove a file or folder inside of the temp directory.<br/>
   <kbd><strong>path*</strong></kbd> <em><code>string</code></em>: The path of the file or folder to remove.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>clone</ins></td>
  <td><em>(path: string, to: string) => !Promise&lt;void&gt;</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Clone a file or directory. This works like <code>cloneGlobal</code>, such that the path won't be resolved automatically.<br/>
   <kbd><strong>path*</strong></kbd> <em><code>string</code></em>: The path to the file or directory to clone.<br/>
   <kbd><strong>to*</strong></kbd> <em><code>string</code></em>: The path to the directory to contain the file or directory being cloned (not the path to the cloned entity).
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>add</ins></td>
  <td><em>(target: string) => !Promise&lt;string&gt;</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Adds a file or directory to the temp directory and returns its new path.<br/>
   <kbd><strong>target*</strong></kbd> <em><code>string</code></em>: The path to the file or directory to add to the temp directory.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>snapshot</ins></td>
  <td><em>(options?: (string | <a href="#type-snapshotoptions">!SnapshotOptions</a>)) => !Promise&lt;string&gt;</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Capture the contents of the temp directory as a string (or partial contents if the inner path is given).<br/>
   <kbd>options</kbd> <em><code>(string \| <a href="#type-snapshotoptions">!SnapshotOptions</a>)</code></em> (optional): When a string is passed, indicates the inner path (left for compatibility with previous API). Otherwise, these are additional options for the snapshot, where inner path can also be specified.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>_destroy</ins></td>
  <td><em>() => !Promise&lt;void&gt;</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Called automatically by a context-testing framework to remove the temp path.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center"><ins>_init</ins></td>
  <td><em>() => !Promise&lt;void&gt;</em></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Called automatically by a context-testing framework to create an empty temp dir.
  </td>
 </tr>
</table>

_For snapshots, the following options can be specified:_

__<a name="type-snapshotoptions">`SnapshotOptions`</a>__
<table>
 <thead><tr>
  <th>Name</th>
  <th>Type &amp; Description</th>
  <th>Default</th>
 </tr></thead>
 <tr>
  <td rowSpan="3" align="center">posix</td>
  <td><em>boolean</em></td>
  <td rowSpan="3"><code>false</code></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   Standardise the path into POSIX (<code>dir/file.txt</code>) &mdash; this is useful when tests are run on Windows too.
  </td>
 </tr>
 <tr>
  <td rowSpan="3" align="center">innerPath</td>
  <td><em>string</em></td>
  <td rowSpan="3"><code>.</code></td>
 </tr>
 <tr></tr>
 <tr>
  <td>
   The path inside of the temp dir to snapshot.
  </td>
 </tr>
</table>

<div align="center"><a href="#table-of-contents">
  <img src="/.documentary/section-breaks/3.svg?sanitize=true">
</a></div>

## **Example**

_Zoroaster_ tests can be written either as masks, or more traditionally as specs. For example, a program might want to write given data to a file in a specified directory, as so:

```js
import { join } from 'path'
import { createWriteStream } from 'fs'

/**
 * Writes given data to a hidden file.
 * @param {string} path Path to the directory where to create a file.
 * @param {string} data Data to write.
 */
const program = async (path, data) => {
  const j = join(path, '.test')
  const rs = createWriteStream(j)
  await new Promise((r) => {
    rs.end(`hello world: ${data}`)
    rs.on('close', r)
  })
}

export default program
```

When writing tests with _Zoroaster_, the project directory will have the `src` and `test` directories:

```m
example
├── src
│   └── index.js
└── test
    ├── context
    │   ├── index.js
    │   └── temp.js
    ├── mask
    │   └── default.js
    ├── result
    │   └── default.md
    └── spec
        ├── default.js
        └── extended.js
```

### Masks

To implement tests with masks, a mask implementation should be set up in the `mask` directory:

```js
import makeTestSuite from '@zoroaster/mask'
import TempContext from 'temp-context'
import program from '../../src'

/**
 * This test suite will clone an input and take a snapshot of the temp directory.
 */
export default makeTestSuite('example/test/result', {
  /**
   * @param {TempContext} context
   */
  async getResults({ TEMP, snapshot }) {
    await program(TEMP, this.input)
    const s = await snapshot()
    return s
  },
  context: TempContext,
})
```

The results file which contains data about how input should be mapped to the output is saved in the `results` directory:

```markdown
## creates a file in the temp directory
input data

/* expected */
# .test

hello world: input data
/**/
```

Now when run, `zoroaster` will use the mask test suite (generated with the `makeTestSuite` function) to check that inputs match expected outputs.

### Specs

Occasionally, there are times when masks are not flexible enough to run tests. Specs are individual test cases, and can access test contexts assigned to the `context` property of a test suite.

```js
import TempContext from 'temp-context'
import { ok, equal } from '@zoroaster/assert'
import Context from '../context'
import program from '../../src'

/** @type {Object.<string, (c:Context, tc: TempContext)>} */
const T = {
  context: [Context, TempContext],
  async 'writes data to a file'(
    { DATA }, { TEMP, resolve, exists, read },
  ) {
    await program(TEMP, DATA)
    const j = resolve('.test')
    console.log('Temp file location: %s', j)

    const e = await exists('.test')
    ok(e, 'File does not exist.')
    const res = await read('.test')
    equal(res, `hello world: ${DATA}`)
  },
}

export default T
```

### Output

The outcome of all the above tests can be achieved with `zoroaster -a example/test/spec example/test/mask` command, where `-a` is used to require [`alamode`](https://alamode.cc) -- a fast RegExp-based transpiler of `import` and `export` statements.

```fs
example/test/spec/default.js
Temp file location: test/temp/.test
  ✓  writes data to a file
 example/test/mask
  ✓  creates a file in the temp directory

🦅  Executed 2 tests.
```

### Autocompletion

One of the advantages of using test context is that they are well documented and it's possible to get auto-completes for available methods when using destructuring on the context argument to a test case, both in masks as well as in specs.

![](images/autocomplete.png)

<div align="center"><a href="#table-of-contents">
  <img src="/.documentary/section-breaks/4.svg?sanitize=true">
</a></div>

## **Extending**

Extending the `TempContext` allows to set the specific temp directory location, and/or add additional methods without having to have 2 contexts for testing.

```js
import TempContext from 'temp-context'

export default class MyTempContext extends TempContext {
  constructor() {
    super()
    this._useOSTemp('package-test')
  }
  get DATA() {
    return 'test-data'
  }
}
```

```js
import { ok, equal } from '@zoroaster/assert'
import MyTempContext from '../context/temp'
import program from '../../src'

/** @type {Object.<string, (tc: MyTempContext)>} */
const T = {
  context: MyTempContext,
  async 'writes data to a file'(
    { TEMP, resolve, exists, read, DATA },
  ) {
    await program(TEMP, DATA)
    const j = resolve('.test')
    console.log('Temp file location: %s', j)

    const e = await exists('.test')
    ok(e, 'File does not exist.')
    const res = await read('.test')
    equal(res, `hello world: ${DATA}`)
  },
}

export default T
```
```fs
example/test/spec/extended.js
Temp file location: /private/var/folders/wj/mc61bmvn3k5_n7q4pfh8rx3w0000gp/T/package-test/.test
  ✓  writes data to a file

🦅  Executed 1 test.
```

<div align="center"><a href="#table-of-contents">
  <img src="/.documentary/section-breaks/5.svg?sanitize=true">
</a></div>

## Copyright

<table>
  <tr>
    <th>
      <a href="https://www.artd.eco">
        <img width="100" src="https://gitlab.com/uploads/-/system/group/avatar/7454762/artdeco.png"
          alt="Art Deco">
      </a>
    </th>
    <th>© <a href="https://www.artd.eco">Art Deco™</a> for <a href="https://wrote.cc">Wrote</a> 2020</th>
    <th>
      <a href="https://wrote.cc">
        <img src="https://avatars3.githubusercontent.com/u/40831417?s=100" width="100" alt="Wrote">
      </a>
    </th>
    <th><a href="LICENSE"><img src=".documentary/agpl-3.0.svg" alt="AGPL-3.0"></a></th>
  </tr>
</table>

<div align="center"><a href="#table-of-contents">
  <img src="/.documentary/section-breaks/-2.svg?sanitize=true">
</a></div>

---
_Source: https://npm.io/package/temp-context · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
