Compare commits
172 Commits
Author | SHA1 | Date |
---|---|---|
dependabot[bot] | 4f4015a4f7 | |
dependabot[bot] | b73ce7bd2e | |
David Humphrey | 3279c2d65a | |
Ben Heidemann | e135305f25 | |
David Humphrey | 0b26979839 | |
Ben Heidemann | 7efc4cdc1d | |
David Humphrey | 4112d072b5 | |
David Humphrey | ee26394ead | |
David Humphrey | 9f8804f716 | |
David Humphrey | 621b6567e0 | |
David Humphrey | 4acd064a2b | |
David Humphrey | b283023286 | |
Arun Bose | 24697a3ed9 | |
dependabot[bot] | 5f872f0f24 | |
bcheidemann | 77abca991a | |
bcheidemann | 49ace4b2fb | |
bcheidemann | d055d8042e | |
bcheidemann | 576831370f | |
bcheidemann | 594ab2621f | |
Ben Heidemann | 75a2cc86cf | |
Ben Heidemann | a4b3726520 | |
Ben Heidemann | 21e7a4750a | |
Ben Heidemann | aa2df3a17c | |
Ben Heidemann | bd15462f6e | |
Ben Heidemann | 78ae19fbad | |
Ben Heidemann | b3caddcfec | |
Ben Heidemann | 11e05e131b | |
Ben Heidemann | fb100b165a | |
Ben Heidemann | e94543471b | |
Ben Heidemann | 20d4d5e720 | |
Ben Heidemann | 0295d19a7f | |
Ben Heidemann | 365a7d23a3 | |
Ben Heidemann | ea5e48b48b | |
Ben Heidemann | e82374ae2b | |
Ben Heidemann | 5bd05287d4 | |
Ben Heidemann | 1c34abf009 | |
Ben Heidemann | 8b4b0a6140 | |
Ben Heidemann | e489409b9c | |
Ben Heidemann | 0db08e31bb | |
Ben Heidemann | 1f02edf5b3 | |
Ben Heidemann | 708c84fc63 | |
Ben Heidemann | 4e45701b51 | |
Ben Heidemann | fe9ed6a648 | |
Ben Heidemann | 81ab65b95c | |
Ben Heidemann | 582352f754 | |
Ben Heidemann | 3b9fafc53e | |
Ben Heidemann | bfb50bf608 | |
Ben Heidemann | ce56539190 | |
Ben Heidemann | 0f812fc6a0 | |
Ben Heidemann | 767c83706b | |
Ben Heidemann | 6a20ac2c3f | |
Ben Heidemann | 2bcf7e560b | |
Ben Heidemann | d040763a73 | |
Ben Heidemann | fd90f32d4c | |
dependabot[bot] | e18104a60d | |
Ben Heidemann | 7bd6e5f4e1 | |
Ben Heidemann | 90db749ee5 | |
Ben Heidemann | f9c5473c49 | |
Ben Heidemann | f5ad682fd7 | |
Ben Heidemann | 7b1c3e85ce | |
Ben Heidemann | 51afeeaf54 | |
Ben Heidemann | cef6adfc37 | |
Ben Heidemann | 6590cb79bd | |
Ben Heidemann | 3e88aeca92 | |
Ben Heidemann | f8c9732be9 | |
David Humphrey | 200171d2a5 | |
David Humphrey | 095f78498f | |
David Humphrey | 5cf2495079 | |
David Humphrey | aacc8061cf | |
Ben Heidemann | c378288819 | |
Ben Heidemann | d1054753a6 | |
bcheidemann | 887ed9318a | |
Ben Heidemann | ce076729f6 | |
bcheidemann | a2151cab25 | |
bcheidemann | 3a8a59d362 | |
bcheidemann | 15be384940 | |
bcheidemann | 6027376efa | |
bcheidemann | 8b57d299f4 | |
bcheidemann | d6b29226aa | |
bcheidemann | da65e06e3c | |
bcheidemann | aa152955b5 | |
bcheidemann | d264113e0d | |
bcheidemann | ce809c4ac9 | |
dependabot[bot] | 3061328459 | |
David Humphrey | c0a41d67ff | |
David Humphrey | 4941d10e13 | |
David Humphrey | 07a00a3f77 | |
bcheidemann | 0f5fe64ae8 | |
bcheidemann | 7ec1fed51f | |
bcheidemann | a2f7ee044b | |
bcheidemann | 7415e45867 | |
bcheidemann | 986ad37597 | |
bcheidemann | 9c669564b2 | |
bcheidemann | 9d03788c1c | |
Ben Heidemann | a60d2b4cfc | |
bcheidemann | 417a4e97dd | |
bcheidemann | 4d4b6bf3f3 | |
bcheidemann | f12f01dca0 | |
bcheidemann | 128e10dc13 | |
bcheidemann | ceed84f377 | |
bcheidemann | 2a581726c6 | |
David Humphrey | 75f2a70c7b | |
David Humphrey | 9db879374d | |
David Humphrey | 98683fe261 | |
SillyFreak | f1fc53d88f | |
Rachael Scotchmer | 4aae53839a | |
dcoull | 94d5ff8795 | |
Charles M Drani | ee56794601 | |
rscotchmer | 914ba8b473 | |
Oleksii Polovyi | 2a4fa0f0fd | |
ApolllonDev | 9d3f220d92 | |
Abdirahman Guled | 3d10d6431c | |
Adel El Masery | 7ab6f5e7c6 | |
kwchan19 | 9487e8ecc6 | |
hoaianhkhang | e6f8ef2251 | |
Paul Moon | f2201e7a74 | |
otkach | 3447ec9c8a | |
David Humphrey (:humph) david.humphrey@senecacollege.ca | fe17870a8f | |
David Humphrey | f4e0dce8d3 | |
Priyanka Dhiman | 34e5580a66 | |
Aqeel Parpia | c515865fb3 | |
Aqeel Parpia | 4887cc725f | |
Aqeel Parpia | 3471848b39 | |
David Humphrey | 9b3e567dd1 | |
David Humphrey | bf18093661 | |
David Humphrey | fa3186d322 | |
David Humphrey | 8a2e64f9ea | |
Alvin Valdez | 0ec51a198d | |
Oleksii Polovyi | 317cee5636 | |
cmchumak | 3c51bbb24f | |
Arash N | 9d4b264479 | |
Sahib Arora | b5e1d9a82b | |
Jacob Adach | da1aad5667 | |
Violet-XiaoWeiHuang | 05057c45d2 | |
Rachael Scotchmer | 4ba9eded4c | |
Woosle Park | 8eaaeeed17 | |
Brandon Wissmann | 3b4bf42604 | |
Harsh Patel | 701849eb5a | |
DavidLi119 | 87513997a2 | |
bonbon12 | 1e660a9d07 | |
Iryna Thompson | 3f619fdcb8 | |
Vincent Logozzo | 43bba422d9 | |
Priyam Brahmbhatt | 7e46fcde8f | |
OlenaVyshnevska | fc545ee3c7 | |
Yuansheng Lu | e5481efa9b | |
Vladimir Rozin | 5918cf6ae7 | |
jatinkumar | 0380a8153c | |
Nathaniel Ngo | 4a39dcc2f0 | |
andrewkoung | 4de0bbfafd | |
Priyanka Dhiman | 7cdef6d963 | |
David Humphrey | 26b47ee094 | |
David Humphrey | 5f10cc2fde | |
David Humphrey | 4e9593f5e8 | |
David Humphrey | 01d76ba0df | |
David Humphrey | dd7536827b | |
David Humphrey | c6e1d51612 | |
David Humphrey | c0acdb97d6 | |
David Humphrey | f4ff2e9ed9 | |
David Humphrey (:humph) david.humphrey@senecacollege.ca | 85a8c21dc1 | |
David Humphrey (:humph) david.humphrey@senecacollege.ca | 9c13a2d248 | |
David Humphrey | 1ad81f9bae | |
David Humphrey (:humph) david.humphrey@senecacollege.ca | bc861bfd4a | |
David Humphrey (:humph) david.humphrey@senecacollege.ca | 11c91acdcf | |
David Humphrey | ace4222a82 | |
David Humphrey | 7301024382 | |
David Humphrey | 6ec8cd6191 | |
David Humphrey | 52baa2523d | |
David Humphrey | d4bfcd71c2 | |
David Humphrey | 4f427ed8d7 | |
David Humphrey | 22731267a9 | |
David Humphrey | 9cb4ff7c0a | |
David Humphrey | 3dea503289 |
|
@ -0,0 +1 @@
|
|||
* text=auto eol=lf
|
|
@ -0,0 +1,27 @@
|
|||
name: node-js-ci
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{matrix.os}}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
node: ['14', '16']
|
||||
|
||||
name: Node ${{ matrix.node }} on ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Test
|
||||
uses: actions/setup-node@v2.4.1
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
- run: npm install
|
||||
- run: npm test
|
|
@ -2,6 +2,7 @@ node_modules
|
|||
.env
|
||||
*~
|
||||
.vscode
|
||||
.idea
|
||||
|
||||
# Parcel build dirs
|
||||
.cache
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
{
|
||||
"scripts": {
|
||||
"beforeStart": "npm run test",
|
||||
"beforeBump": "npm run build",
|
||||
"changelogCommand": "git log --pretty=format:'* %s (%h)' [REV_RANGE]"
|
||||
"hooks": {
|
||||
"before:init": ["npm run test"],
|
||||
"before:bump": ["npm run build"]
|
||||
},
|
||||
"git": {
|
||||
"pushRepo": "git@github.com:filerjs/filer.git",
|
||||
"tagName": "v%s"
|
||||
"tagName": "v${version}"
|
||||
},
|
||||
"npm": {
|
||||
"publish": true
|
||||
},
|
||||
"github": {
|
||||
"release": true,
|
||||
"releaseName": "Filer.js %s Released"
|
||||
"pushRepo": "git@github.com:filerjs/filer.git",
|
||||
"release": true
|
||||
}
|
||||
}
|
||||
|
|
2
AUTHORS
2
AUTHORS
|
@ -5,3 +5,5 @@ Barry Tulchinsky <barry.tulchinsky@gmail.com> (@btulchinsky)
|
|||
Kieran Sedgwick <kieran.sedgwick@gmail.com> (@sedge)
|
||||
Yoav Gurevich <ygurevich@ymail.com>
|
||||
Gideon Thomas <r.gideonthomas@gmail.com>
|
||||
Abdirahman Guled <aguled2@myseneca.ca>
|
||||
Ben Heidemann <ben@heidemann.co.uk>
|
|
@ -15,47 +15,55 @@ To get a working build system do the following:
|
|||
npm install
|
||||
```
|
||||
|
||||
You can now run the following `npm` scripts:
|
||||
|
||||
* `npm run lint` or `npm run eslint` will run `eslint` on the `src` and `tests` directories.
|
||||
* `npm run lint:fix` or `npm run eslint:fix` will run `eslint` with `--fix` on the `src` and `tests` directories, automatically fixing minor issues.
|
||||
* `npm run test:manual` will build the tests, and allow you to run them in a browser manually by loading http://localhost:1234.
|
||||
* `npm run karma-mocha` will build Filer and the tests, and finally run the tests in both headless Chrome and headless Firefox browsers.
|
||||
* `npm run karma-mocha-chrome` will build Filer and the tests, and finally run the tests in headless Chrome
|
||||
* `npm run karma-mocha-firefox` will build Filer and the tests, and finally run the tests in headless Firefox
|
||||
* `npm test` will run `lint` followed by `karma-chrome`, and is what we do on Travis.
|
||||
* `npm run build` will bundle two versions of Filer: `dist/filer.js` (unminified) and `dist/filer.min.js` (minified) as well as source map files.
|
||||
|
||||
Once you've done some hacking and you'd like to have your work merged, you'll need to
|
||||
make a pull request. If your patch includes code, make sure to check that all the
|
||||
unit tests pass, including any new tests you wrote. Finally, make sure you add yourself
|
||||
to the `AUTHORS` file.
|
||||
Next, make sure you have installed Chrome and Firefox, which are needed for
|
||||
running headless versions of the tests with `npm test`.
|
||||
|
||||
## Tests
|
||||
|
||||
Tests are writting using [Mocha](http://visionmedia.github.io/mocha/) and [Chai](http://chaijs.com/api/bdd/).
|
||||
You can run the tests in your browser by running `npm test` and opening your browser to `http://localhost:1234`.
|
||||
Tests are written using [Mocha](https://mochajs.org/) and [Chai](http://chaijs.com/api/bdd/).
|
||||
There are a number of ways to run the tests. The preferred way is:
|
||||
|
||||
```
|
||||
npm test
|
||||
```
|
||||
|
||||
This will do a build, run the linting, start a server, and load the tests into
|
||||
headless versions of Chrome and Firefox.
|
||||
|
||||
If you want more control over how tests are run, you can use other scripts:
|
||||
|
||||
* Linting is done via `npm run lint` or `npm run eslint`, both of which will run `eslint` on the `src` and `tests` directories. You can also use `npm run lint:fix` or `npm run eslint:fix`, which will run `eslint` with `--fix` on the `src` and `tests` directories, automatically fixing minor issues. Linting is run by default as part of `npm test`
|
||||
|
||||
* In headless versions of Chrome and Firefox using `npm test`. A report at the end will tell you what happened with each browser. Browser tests are preferred because they also test our providers (e.g., IndexedDB). They do take longer to run. You can also use `npm run karma-mocha-firefox` or `npm run karma-mocha-chrome` to run the tests in only one of the two headless browsers.
|
||||
|
||||
* In node.js using the Memory provider using `npm run test:node`. These run much faster, but don't run all tests (e.g., providers, watches).
|
||||
|
||||
* If you need to debug browser tests, or want to run them in a different browser, use `npm run test:manual`, which will start a server and you can point your browser to [http://localhost:1234](http://localhost:1234). Running the tests this way will also automatically watch your files, and hot-reload your code and tests, which is useful for debugging and trial/error testing.
|
||||
|
||||
* If you need to debug node.js test runs, you can do so using `npm run test:node-debug`. Then, open Chrome and browse to [chrome://inspect](chrome://inspect) and click on your tests in the inspector. The easiest way to get a breakpoint is to manually add a `debugger` keyword to your test code where you want the tests to stop.
|
||||
|
||||
> Tip: you can add `skip()` to any `it()` or `describe()` in Mocha to skip a test, or `only()` to have only that test run. For example: `describe.skip(...)` or `it.only(...)`.
|
||||
|
||||
* If you want to run migration tests separate from unit tests, use `npm run test:migrations`. Migration tests run at the end of a typical `npm test` run. If you need to create a new migration test, see [`tools/fs-image.js`](tools/fs-image.js) for details on how to generate a filesystem image, and [tests/filesystems/images/README.md](tests/filesystems/images/README.md) for more docs.
|
||||
|
||||
* If you want to manually generate coverage info for the tests, use `npm run coverage`. This is done automatically in Travis, so you shouldn't need to do it. You can see [https://codecov.io/gh/filerjs/filer](https://codecov.io/gh/filerjs/filer) for detailed reports.
|
||||
|
||||
There are a number of configurable options for the test suite, which are set via query string params.
|
||||
First, you can choose which filer source to use (i.e., src/, dist/filer-test.js, dist/filer.js or dist/filer.min.js).
|
||||
The default is to use what is in /dist/filer-test.js, and you can switch to other versions like so:
|
||||
First, you can choose which filer source to use (i.e., src/, dist/filer-test.js, dist/filer.js or dist/filer.min.js). The default is to use what is in /dist/filer-test.js, and you can switch to other versions like so:
|
||||
|
||||
* tests/index.html?filer-dist/filer.js
|
||||
* tests/index.html?filer-dist/filer.min.js
|
||||
* tests/index.html?filer-src/filer.js (from src)
|
||||
|
||||
Second, you can specify which provider to use for all non-provider specific tests (i.e., most of the tests).
|
||||
The default provider is `Memory`, and you can switch it like so:
|
||||
|
||||
* tests/index.html?filer-provider=memory
|
||||
* tests/index.html?filer-provider=indexeddb
|
||||
* tests/index.html?filer-provider=websql
|
||||
|
||||
If you're writing tests, make sure you write them in the same style as existing tests, which are
|
||||
provider agnostic. See `tests/lib/test-utils.js` and how it gets used in various tests as
|
||||
an example.
|
||||
|
||||
## Communication
|
||||
|
||||
If you'd like to talk to someone about the project, you can reach us on irc.mozilla.org in the #filer or #mofodev channel. Look for "ack" or "humph".
|
||||
provider agnostic. See [`tests/lib/test-utils.js`](tests/lib/test-utils.js) and how it gets used
|
||||
in various tests as an example.
|
||||
|
||||
## Releases
|
||||
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2013, Alan Kligman
|
||||
Copyright (c) 2013 - 2019 Alan Kligman and the Filer contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
|
248
README.md
248
README.md
|
@ -1,28 +1,26 @@
|
|||
[![NPM](https://nodei.co/npm/filer.png?downloads=true&stars=true)](https://nodei.co/npm/filer/)
|
||||
|
||||
[![Build Status](https://secure.travis-ci.org/filerjs/filer.png?branch=develop)](http://travis-ci.org/filerjs/filer)
|
||||
|
||||
[![codecov](https://codecov.io/gh/filerjs/filer/branch/master/graph/badge.svg)](https://codecov.io/gh/filerjs/filer)
|
||||
[![Build Status](https://secure.travis-ci.org/filerjs/filer.png?branch=develop)](http://travis-ci.org/filerjs/filer) [![codecov](https://codecov.io/gh/filerjs/filer/branch/master/graph/badge.svg)](https://codecov.io/gh/filerjs/filer)
|
||||
|
||||
### Filer
|
||||
|
||||
Filer is a POSIX-like file system interface for node.js and browser-based JavaScript.
|
||||
Filer is a drop-in replacement for node's `fs` module, a POSIX-like file system
|
||||
for browsers.
|
||||
|
||||
### Compatibility
|
||||
|
||||
Filer is known to work in the following browsers/versions, with the specified [Storage Providers](#providers):
|
||||
Filer uses [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)
|
||||
and is [known to work in the following browsers/versions](https://caniuse.com/#feat=indexeddb):
|
||||
|
||||
* node.js: v0.10.*+
|
||||
* IE: 10+ (IndexedDB)
|
||||
* Firefox: 26+ (IndexedDB)
|
||||
* Chrome: 31+ (IndexedDB, WebSQL)
|
||||
* Safari: 7.0+ (WebSQL)
|
||||
* Opera: 19+ (IndexedDB, WebSQL)
|
||||
* iOS: 3.2+ (WebSQL)
|
||||
* Android Browser: 2.1-4.4 (WebSQL), 4.4+ (IndexedDB)
|
||||
|
||||
NOTE: if you're interested in maximum compatibility, use the `Fallback` provider instead of `Default`.
|
||||
See the section on [Storage Providers](#providers).
|
||||
* IE: 10+
|
||||
* Edge: 12+
|
||||
* Firefox: 10+
|
||||
* Chrome: 23+
|
||||
* Safari: 10+
|
||||
* Opera: 15+
|
||||
* iOS: 10+
|
||||
* Android Browser: 4.4+
|
||||
|
||||
### Contributing
|
||||
|
||||
|
@ -32,16 +30,15 @@ Want to join the fun? We'd love to have you! See [CONTRIBUTING](https://github.c
|
|||
|
||||
Filer can be obtained in a number of ways:
|
||||
|
||||
1. npm - `npm install filer`
|
||||
2. bower - `bower install filer`
|
||||
3. download pre-built versions: [filer.js](https://raw.github.com/filerjs/filer/develop/dist/filer.js), [filer.min.js](https://raw.github.com/filerjs/filer/develop/dist/filer.min.js)
|
||||
1. Via npm: `npm install filer`
|
||||
1. Via unpkg: `<script src="https://unpkg.com/filer"></script>` or specify a version directly, for example: [https://unpkg.com/filer@1.0.1/dist/filer.min.js](https://unpkg.com/filer@1.0.1/dist/filer.min.js)
|
||||
|
||||
### Loading and Usage
|
||||
|
||||
Filer is built as a UMD module and can therefore be loaded as a CommonJS or AMD module, or used via the global.
|
||||
|
||||
```javascript
|
||||
// Option 1: Filer loaded via require() in node/browserify
|
||||
// Option 1: Filer loaded via require()
|
||||
var Filer = require('filer');
|
||||
|
||||
// Option 2: Filer loaded via RequireJS
|
||||
|
@ -57,6 +54,78 @@ requirejs(['filer'], function(Filer) {...}
|
|||
var Filer = window.Filer;
|
||||
```
|
||||
|
||||
### Webpack Plugin
|
||||
|
||||
Filer can be used as a drop-in replacement for the node.js [fs](http://nodejs.org/api/fs.html) and
|
||||
[path](http://nodejs.org/api/path.html) modules. For convenience, filer provides a webpack plugin which
|
||||
will shim the desired node.js functionality. This plugin can be used by inserting the following into
|
||||
your webpack config:
|
||||
|
||||
```javascript
|
||||
// webpack.config.js
|
||||
var { FilerWebpackPlugin } = require('filer/webpack');
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
new FilerWebpackPlugin(),
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
**NOTE**
|
||||
|
||||
Previously it was recommended to access the `FilerWebpackPlugin` class by importing the main filer module. This was depracated due [this issue](https://github.com/filerjs/filer/issues/790). For anyone using ***filer version 1.4.0 or earlier***, please import the plugin class like this:
|
||||
|
||||
```javascript
|
||||
var FilerWebpackPlugin = require('filer/src/webpack-plugin');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
You can then import the node.js [fs](http://nodejs.org/api/fs.html) and [path](http://nodejs.org/api/path.html)
|
||||
modules as normal and `FilerWebpackPlugin` will ensure that webpack will resolve references to these modules to
|
||||
the appropriate filer shims. You will then be able to use these modules as normal (with the exception of the
|
||||
synchronous fs methods e.g. `mkdirSync()`).
|
||||
|
||||
```javascript
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
```
|
||||
|
||||
The filer webpack plugin will, by default, shim the [fs](http://nodejs.org/api/fs.html) and
|
||||
[path](http://nodejs.org/api/path.html) modules. However, it's behaviour can be customised by passing an
|
||||
options object.
|
||||
|
||||
```javascript
|
||||
// webpack.config.js
|
||||
module.exports = {
|
||||
plugins: [
|
||||
new FilerWebpackPlugin({
|
||||
// Options
|
||||
}),
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
The following options can be passed to the filer webpack plugin:
|
||||
|
||||
| Option | Type | Optional | Default | Description |
|
||||
|---------------|---------|----------|--------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| filerDir | string | yes | '\<rootDir\>/node_modules/filer' | The directory in which filer is installed. |
|
||||
| shimsDir | string | yes | '\<rootDir\>/node_modules/filer/shims' | The directory in which the shims are installed. |
|
||||
| fsProviderDir | string | yes | '\<rootDir\>/node_modules/filer/shims/providers' | The directory in which the shims are located. This option is required when using a custom provider. |
|
||||
| shimFs | boolean | yes | true | Should the fs module be shimmed. |
|
||||
| shimPath | boolean | yes | true | Should the path module be shimmed. |
|
||||
| fsProvider | string | yes | 'default' | The file system provider to use. Should be one of 'default', 'indexeddb', 'memory', 'custom'. The 'default' option is equivalent to 'indexeddb'. |
|
||||
|
||||
NOTE: '\<rootDir\>' will be resolved to the current working directory.
|
||||
|
||||
Though filer also exposes the Buffer object, it is left up to the user to shim this as appropriate. This is because filer offers
|
||||
no custom implementation. Currently, filer uses the [node-libs-browser](https://github.com/webpack/node-libs-browser) Buffer implementation
|
||||
internally, though any faithful implementation of the [node.js Buffer object](http://nodejs.org/api/buffer.html) should play nicely
|
||||
with filer.
|
||||
|
||||
### Getting Started
|
||||
|
||||
Filer is as close to the node.js [fs module](http://nodejs.org/api/fs.html) as possible,
|
||||
|
@ -79,19 +148,32 @@ they are invoked. Ensure proper ordering by chaining operations in callbacks.
|
|||
To create a new file system or open an existing one, create a new `FileSystem`
|
||||
instance. By default, a new [IndexedDB](https://developer.mozilla.org/en/docs/IndexedDB)
|
||||
database is created for each file system. The file system can also use other
|
||||
backend storage providers, for example [WebSQL](http://en.wikipedia.org/wiki/Web_SQL_Database)
|
||||
or even RAM (i.e., for temporary storage). See the section on [Storage Providers](#providers).
|
||||
backend storage providers, for example `Memory`. See the section on [Storage Providers](#providers).
|
||||
|
||||
<a name="overviewExample"></a>
|
||||
|
||||
```javascript
|
||||
var fs = new Filer.FileSystem();
|
||||
fs.open('/myfile', 'w+', function(err, fd) {
|
||||
if (err) throw err;
|
||||
fs.close(fd, function(err) {
|
||||
if (err) throw err;
|
||||
fs.stat('/myfile', function(err, stats) {
|
||||
if (err) throw err;
|
||||
console.log('stats: ' + JSON.stringify(stats));
|
||||
```js
|
||||
const { fs, path } = require('filer');
|
||||
|
||||
fs.mkdir('/docs', (err) => {
|
||||
if (err) {
|
||||
return console.error('Unable to create /docs dir', err);
|
||||
}
|
||||
|
||||
const filename = path.join('/docs', 'first.txt');
|
||||
const data = 'Hello World!\n';
|
||||
|
||||
fs.writeFile(filename, data, (err) => {
|
||||
if (err) {
|
||||
return console.error('Unable to write /docs/first.txt', err);
|
||||
}
|
||||
|
||||
fs.stat(filename, (err, stats) => {
|
||||
if (err) {
|
||||
return console.error('Unable to stat /docs/first.txt', err);
|
||||
}
|
||||
|
||||
console.log('Stats for /docs/first.txt:', stats);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -100,7 +182,7 @@ fs.open('/myfile', 'w+', function(err, fd) {
|
|||
For a complete list of `FileSystem` methods and examples, see the [FileSystem Instance Methods](#FileSystemMethods)
|
||||
section below.
|
||||
|
||||
Filer also supports node's Path module. See the [Filer.Path](#FilerPath) section below.
|
||||
Filer also includes node's `path` and `Buffer` modules. See the [Filer.Path](#FilerPath) and [Filer.Buffer](#FilerBuffer) sections below.
|
||||
|
||||
In addition, common shell operations (e.g., rm, touch, cat, etc.) are supported via the
|
||||
`FileSystemShell` object, which can be obtained from, and used with a `FileSystem`.
|
||||
|
@ -113,25 +195,28 @@ you omit the callback, errors will be thrown as exceptions). The first callback
|
|||
reserved for passing errors. It will be `null` if no errors occurred and should always be checked.
|
||||
|
||||
#### Support for Promises
|
||||
The Promise based API mimics the way Node [implements](https://nodejs.org/api/fs.html#fs_fs_promises_api) them. Both `Shell` and `FileSystem` now have a `promises` object attached alongside the regular callback style methods. Method names are identical to their callback counterparts with the difference that instead of receiving a final argument as a callback, they return a Promise that is resolved or rejected based on the success of method execution.
|
||||
> Please note that `exists` method will always throw, since it was [deprecated](https://nodejs.org/api/fs.html#fs_fs_exists_path_callback) by Node.
|
||||
|
||||
The Promise based API mimics the way node [implements](https://nodejs.org/api/fs.html#fs_fs_promises_api) them. Both `Shell` and `FileSystem` now have a `promises` property, which gives access to Promise based versions of methods in addition to the regular callback style methods. Method names are identical to their callback counterparts with the difference that instead of receiving a final argument as a callback, they return a Promise that is resolved or rejected based on the success of method execution.
|
||||
|
||||
See example below:
|
||||
|
||||
```javascript
|
||||
const fs = new Filer.FileSystem().promises;
|
||||
fs.open('/myfile', 'w+')
|
||||
.then(fd => fs.close(fd))
|
||||
fs.writeFile('/myfile', 'some data')
|
||||
.then(() => fs.stat('/myfile'))
|
||||
.then(stats => { console.log(`stats: ${JSON.stringify(stats)}`); })
|
||||
.catch(err => { console.error(err); })
|
||||
.catch(err => { console.error(err); });
|
||||
```
|
||||
> The callback style usage could be found [here](#overviewExample).
|
||||
|
||||
#### Filer.FileSystem(options, callback) constructor
|
||||
|
||||
File system constructor, invoked to open an existing file system or create a new one.
|
||||
Accepts two arguments: an `options` object, and an optional `callback`. The `options`
|
||||
object can specify a number of optional arguments, including:
|
||||
In most cases, using `Filer.fs` will be sufficient, and provide a working filesystem.
|
||||
However, if you need more control over the filesystem, you can also use the `FileSystem`
|
||||
constructor, invoked to open an existing file system or create a new one.
|
||||
|
||||
`Filer.FileSystem()` It accepts two arguments: an `options` object, and an optional
|
||||
`callback` function. The `options` object can specify a number of optional arguments,
|
||||
including:
|
||||
|
||||
* `name`: the name of the file system, defaults to `'"local'`
|
||||
* `flags`: an Array of one or more flags to use when creating/opening the file system:
|
||||
|
@ -166,15 +251,17 @@ it becomes ready.
|
|||
|
||||
#### Filer.FileSystem.providers - Storage Providers<a name="providers"></a>
|
||||
|
||||
Filer can be configured to use a number of different storage providers. The provider object encapsulates all aspects
|
||||
of data access, making it possible to swap in different backend storage options. There are currently 4 different
|
||||
providers to choose from:
|
||||
Filer can be configured to use a number of different storage providers. The provider object encapsulates all aspects of data access, making it possible to swap in different backend storage options. There are currently 2 providers to choose from:
|
||||
|
||||
* `FileSystem.providers.IndexedDB()` - uses IndexedDB
|
||||
* `FileSystem.providers.WebSQL()` - uses WebSQL
|
||||
* `FileSystem.providers.Fallback()` - attempts to use IndexedDB if possible, falling-back to WebSQL if necessary
|
||||
if necessary
|
||||
* `FileSystem.providers.Memory()` - uses memory (not suitable for data that needs to survive the current session)
|
||||
|
||||
**NOTE**: previous versions of Filer also supported `FileSystem.providers.WebSQL()` and
|
||||
`FileSystem.providers.Fallback()`, which could be used in browsers that supported
|
||||
WebSQL but not IndexedDB. [WebSQL has been deprecated](https://www.w3.org/TR/webdatabase/),
|
||||
and this functionality was removed in `v1.0.0`. If for some reason you still need it, use [`v0.0.44`](https://github.com/filerjs/filer/releases/tag/v0.0.44).
|
||||
|
||||
You can choose your provider when creating a `FileSystem`:
|
||||
|
||||
```javascript
|
||||
|
@ -184,28 +271,20 @@ var providers = FileSystem.providers;
|
|||
// Example 1: Use the default provider (currently IndexedDB)
|
||||
var fs1 = new FileSystem();
|
||||
|
||||
// Example 2: Explicitly use IndexedDB
|
||||
var fs2 = new FileSystem({ provider: new providers.IndexedDB() });
|
||||
|
||||
// Example 3: Use one of IndexedDB or WebSQL, whichever is supported
|
||||
var fs3 = new FileSystem({ provider: new providers.Fallback() });
|
||||
// Example 2: Use the Memory provider
|
||||
var fs2 = new FileSystem({ provider: new providers.Memory() });
|
||||
```
|
||||
|
||||
Every provider has an `isSupported()` method, which returns `true` if the browser supports this provider:
|
||||
|
||||
```javascript
|
||||
if( Filer.FileSystem.providers.WebSQL.isSupported() ) {
|
||||
// WebSQL provider will work in current environment...
|
||||
if( Filer.FileSystem.providers.IndexedDB.isSupported() ) {
|
||||
// IndexedDB provider will work in current environment...
|
||||
}
|
||||
```
|
||||
|
||||
You can also write your own provider if you need a different backend. See the code in `src/providers` for details.
|
||||
|
||||
A number of other providers have been written, including:
|
||||
|
||||
* node.js fs provider: https://github.com/humphd/filer-fs
|
||||
* node.js Amazon S3 provider: https://github.com/alicoding/filer-s3
|
||||
|
||||
#### Filer.Buffer<a name="FilerBuffer"></a>
|
||||
|
||||
When reading and writing data, Filer follows node.js and uses [`Buffer`](http://nodejs.org/api/buffer.html).
|
||||
|
@ -238,12 +317,16 @@ Buffer.allocUnsafe(size)
|
|||
|
||||
#### Filer.Path<a name="FilerPath"></a>
|
||||
|
||||
The node.js [path module](http://nodejs.org/api/path.html) is available via the `Filer.Path` object. It is
|
||||
identical to the node.js version with the following differences:
|
||||
* No notion of a current working directory in `resolve` (the root dir is used instead)
|
||||
The node.js [path module](http://nodejs.org/api/path.html) is available via `Filer.path` or
|
||||
`Filer.Path` (both are supported for historical reasons, and to match node). The Filer `path`
|
||||
module is identical to the node.js version (see [https://github.com/browserify/path-browserify](https://github.com/browserify/path-browserify)), with the following differences:
|
||||
|
||||
* The CWD always defaults to `/`
|
||||
* No support for Windows style paths (assume you are on a POSIX system)
|
||||
* Additional utility methods (see below)
|
||||
|
||||
```javascript
|
||||
var path = Filer.Path;
|
||||
var path = Filer.path;
|
||||
var dir = path.dirname('/foo/bar/baz/asdf/quux');
|
||||
// dir is now '/foo/bar/baz/asdf'
|
||||
|
||||
|
@ -258,16 +341,37 @@ var newpath = path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
|
|||
```
|
||||
|
||||
For more info see the docs in the [path module](http://nodejs.org/api/path.html) for a particular method:
|
||||
* `path.normalize(p)`
|
||||
* `path.normalize(p)` - NOTE: Filer.Path.normalize does *not* add a trailing slash
|
||||
* `path.join([path1], [path2], [...])`
|
||||
* `path.resolve([from ...], to)`
|
||||
* `path.relative(from, to)`
|
||||
* `path.dirname(p)`
|
||||
* `path.basename(p, [ext])`
|
||||
* `path.basename(p, [ext])` - NOTE: Filer.Path.basename will return `'/'` vs. `''`
|
||||
* `path.extname(p)`
|
||||
* `path.sep`
|
||||
* `path.delimiter`
|
||||
|
||||
Filer.Path also includes the following extra methods:
|
||||
|
||||
* `isNull(p)` returns `true` or `false` if the path contains a null character (`'\u0000'`)
|
||||
* `addTrailing(p)` returns the path `p` with a single trailing slash added
|
||||
* `removeTrailing(p)` returns the path `p` with trailing slash(es) removed
|
||||
|
||||
[As with node.js](https://nodejs.org/api/fs.html#fs_file_paths), all methods below that
|
||||
accept a `path` argument as a `String` can also take a [`file://` URL](https://nodejs.org/api/fs.html#fs_url_object_support)
|
||||
or a `Buffer`. For example, all of the following cases will work the same way with Filer:
|
||||
|
||||
```js
|
||||
// 1. path as a String
|
||||
fs.writeFile('/dir/file.txt', 'data', function(err) {...});
|
||||
|
||||
// 2. path as a URL
|
||||
fs.writeFile(new URL('file:///dir/file.txt'), 'data', function(err) {...});
|
||||
|
||||
// 3. path as a Buffer
|
||||
fs.writeFile(Buffer.from('/dir/file.txt'), 'data', function(err) {...});
|
||||
```
|
||||
|
||||
#### Filer.Errors<a name="Errors"></a>
|
||||
|
||||
The error objects used internally by Filer are also exposed via the `Filer.Errors` object. As much as possible
|
||||
|
@ -310,7 +414,11 @@ Once a `FileSystem` is created, it has the following methods. NOTE: code example
|
|||
a `FileSystem` instance named `fs` has been created like so:
|
||||
|
||||
```javascript
|
||||
var fs = new Filer.FileSystem();
|
||||
// 1. Using Filer.fs for a default filesystem
|
||||
const { fs } = require('filer');
|
||||
|
||||
// 2. Or via the FileSystem constructor with specified options
|
||||
const fs = new Filer.FileSystem(options, callback);
|
||||
```
|
||||
|
||||
* [fs.rename(oldPath, newPath, callback)](#rename)
|
||||
|
@ -714,7 +822,7 @@ fs.mkdir('/home', function(err) {
|
|||
|
||||
#### fs.access(path, [mode], callback)<a name="access"></a>
|
||||
|
||||
Tests a user's permissions for the file or directory supplied in `path` argument. Asynchronous [access(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/access.html). Callback gets no additional arguments. The `mode` argument can be one of the following (constants are available on `fs.constants`):
|
||||
Tests a user's permissions for the file or directory supplied in `path` argument. Asynchronous [access(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/access.html). Callback gets no additional arguments. The `mode` argument can be one of the following (constants are available on `fs.constants` and `fs`):
|
||||
|
||||
* `F_OK`: Test for existence of file.
|
||||
* `R_OK`: Test whether the file exists and grants read permission.
|
||||
|
@ -727,7 +835,7 @@ Example:
|
|||
|
||||
```javascript
|
||||
// Check if the file exists in the current directory.
|
||||
fs.access(file, fs.constants.F_OK, function(err) {
|
||||
fs.access(file, fs.F_OK, function(err) {
|
||||
console.log(`${file} ${err ? 'does not exist' : 'exists'}`);
|
||||
});
|
||||
```
|
||||
|
@ -752,7 +860,7 @@ fs.mkdtemp("/myDir/tmp", function (error, path) {
|
|||
});
|
||||
```
|
||||
|
||||
#### fs.readdir(path, callback)<a name="readdir"></a>
|
||||
#### fs.readdir(path, [options], callback)<a name="readdir"></a>
|
||||
|
||||
Reads the contents of a directory. Asynchronous [readdir(3)](http://pubs.opengroup.org/onlinepubs/009695399/functions/readdir.html).
|
||||
Callback gets `(error, files)`, where `files` is an array containing the names of each directory entry (i.e., file, directory, link) in the directory, excluding `.` and `..`.
|
||||
|
@ -773,6 +881,12 @@ fs.readdir('/docs', function(err, files) {
|
|||
});
|
||||
```
|
||||
|
||||
Optionally accepts an options parameter, which can be either an encoding (e.g. "utf8") or an object with optional properties `encoding` and `withFileTypes`.
|
||||
|
||||
The `encoding` property is a `string` which will determine the character encoding to use for the names of each directory entry. The `withFileTypes` property is a `boolean` which defaults to `false`. If `true`, this method will return an array of [fs.Dirent](https://nodejs.org/api/fs.html#fs_class_fs_dirent) objects.
|
||||
|
||||
The `name` property on the [fs.Dirent](https://nodejs.org/api/fs.html#fs_class_fs_dirent) objects will be encoded using the specified character encoding.
|
||||
|
||||
#### fs.close(fd, callback)<a name="close"></a>
|
||||
|
||||
Closes a file descriptor. Asynchronous [close(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/close.html).
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -2,10 +2,14 @@ module.exports = function(config) {
|
|||
config.set({
|
||||
singleRun: true,
|
||||
basePath: '',
|
||||
files: ['tests/dist/index.js'],
|
||||
files: [
|
||||
'node_modules/regenerator-runtime/runtime.js',
|
||||
'tests/dist/index.js'
|
||||
],
|
||||
frameworks: ['mocha', 'chai'],
|
||||
reporters: ['mocha', 'summary'],
|
||||
client: {
|
||||
captureConsole: true,
|
||||
mocha: {
|
||||
ui: 'bdd',
|
||||
timeout: 5000,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
56
package.json
56
package.json
|
@ -5,13 +5,12 @@
|
|||
"fs",
|
||||
"node",
|
||||
"file",
|
||||
"system",
|
||||
"filesystem",
|
||||
"browser",
|
||||
"indexeddb",
|
||||
"idb",
|
||||
"websql"
|
||||
"idb"
|
||||
],
|
||||
"version": "1.0.0",
|
||||
"version": "1.4.1",
|
||||
"author": "Alan K <ack@modeswitch.org> (http://blog.modeswitch.org)",
|
||||
"homepage": "http://filerjs.github.io/filer",
|
||||
"bugs": "https://github.com/filerjs/filer/issues",
|
||||
|
@ -21,6 +20,9 @@
|
|||
"eslint:fix": "npm run lint:fix",
|
||||
"lint": "eslint src tests",
|
||||
"lint:fix": "eslint --fix src tests",
|
||||
"test:node": "mocha --timeout 5000 tests",
|
||||
"pretest:node-debug": "echo \"Open Chrome to chrome://inspect to debug tests...\"",
|
||||
"test:node-debug": "mocha --timeout 5000 --inspect-brk tests",
|
||||
"test:manual": "parcel tests/index.html --out-dir tests/dist",
|
||||
"test:migrations": "mocha tests/filesystems/migrations",
|
||||
"pretest": "npm run lint",
|
||||
|
@ -43,35 +45,41 @@
|
|||
"url": "https://github.com/filerjs/filer.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"base64-arraybuffer": "^0.1.5",
|
||||
"es6-promisify": "^6.0.0",
|
||||
"minimatch": "^3.0.4"
|
||||
"es6-promisify": "^7.0.0",
|
||||
"minimatch": "^3.0.4",
|
||||
"schema-utils": "^3.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.1.2",
|
||||
"chai-datetime": "^1.5.0",
|
||||
"eslint": "^5.0.1",
|
||||
"karma": "^3.0.0",
|
||||
"regenerator-runtime": "^0.13.9",
|
||||
"chai": "^4.3.4",
|
||||
"chai-datetime": "^1.8.0",
|
||||
"eslint": "^7.32.0",
|
||||
"fake-indexeddb": "^3.1.7",
|
||||
"karma": "^6.3.8",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-firefox-launcher": "^1.1.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-chrome-launcher": "^3.1.0",
|
||||
"karma-firefox-launcher": "^2.1.2",
|
||||
"karma-mocha": "^2.0.1",
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
"karma-summary-reporter": "^1.5.1",
|
||||
"meow": "^5.0.0",
|
||||
"mocha": "^5.2.0",
|
||||
"nyc": "^13.1.0",
|
||||
"parcel-bundler": "^1.10.3",
|
||||
"pretty-bytes": "^5.1.0",
|
||||
"release-it": "^9.2.0",
|
||||
"karma-summary-reporter": "^3.0.0",
|
||||
"meow": "^10.0.1",
|
||||
"mocha": "^9.1.3",
|
||||
"nyc": "^15.1.0",
|
||||
"parcel-bundler": "^1.12.5",
|
||||
"pretty-bytes": "^5.6.0",
|
||||
"release-it": "^14.11.6",
|
||||
"run.env": "^1.1.0",
|
||||
"unused-filename": "^1.0.0",
|
||||
"walk": "^2.3.14"
|
||||
"unused-filename": "^3.0.1",
|
||||
"walk": "^2.3.15"
|
||||
},
|
||||
"main": "./src/index.js",
|
||||
"browser": "./dist/filer.min.js",
|
||||
"files": [
|
||||
"dist"
|
||||
"src",
|
||||
"lib",
|
||||
"dist",
|
||||
"shims",
|
||||
"webpack"
|
||||
],
|
||||
"nyc": {
|
||||
"exclude": [
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
const { FileSystem } = require('../src/index');
|
||||
|
||||
let Provider;
|
||||
try {
|
||||
Provider = require('fsProvider');
|
||||
}
|
||||
catch (err) {
|
||||
Provider = require('./providers/default');
|
||||
}
|
||||
|
||||
const provider = new Provider();
|
||||
|
||||
let onFsReady;
|
||||
let onFsError;
|
||||
|
||||
let fsReady = new Promise((resolve, reject) => {
|
||||
onFsReady = resolve;
|
||||
onFsError = reject;
|
||||
});
|
||||
|
||||
var fsInstance = new FileSystem({ provider }, (err) => {
|
||||
if (err) {
|
||||
onFsError(err);
|
||||
} else {
|
||||
onFsReady(true);
|
||||
}
|
||||
});
|
||||
|
||||
function proxyHasProp(target, prop) {
|
||||
return prop in target;
|
||||
}
|
||||
|
||||
const fsPromises = new Proxy(fsInstance.promises, {
|
||||
get(target, prop) {
|
||||
if (!proxyHasProp(target, prop)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return async (...args) => {
|
||||
await fsReady;
|
||||
return await target[prop](...args);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const fs = new Proxy(fsInstance, {
|
||||
get(target, prop) {
|
||||
if (!proxyHasProp(target, prop)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop === 'promises') {
|
||||
return fsPromises;
|
||||
}
|
||||
|
||||
return (...args) => {
|
||||
(async () => {
|
||||
await fsReady;
|
||||
target[prop](...args);
|
||||
})();
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = fs;
|
|
@ -0,0 +1,3 @@
|
|||
const { path } = require('../src/index');
|
||||
|
||||
module.exports = path;
|
|
@ -0,0 +1,2 @@
|
|||
const { Default } = require('../../src/providers/index');
|
||||
module.exports = Default;
|
|
@ -0,0 +1,2 @@
|
|||
const IndexedDB = require('../../src/providers/indexeddb');
|
||||
module.exports = IndexedDB;
|
|
@ -0,0 +1,2 @@
|
|||
const Memory = require('../../src/providers/memory');
|
||||
module.exports = Memory;
|
|
@ -0,0 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
const Stats = require('./stats.js');
|
||||
|
||||
function Dirent(path, fileNode, devName) {
|
||||
this.constructor = Dirent;
|
||||
Stats.call(this, path, fileNode, devName);
|
||||
}
|
||||
|
||||
Dirent.prototype = Stats.prototype;
|
||||
|
||||
module.exports = Dirent;
|
|
@ -1,4 +0,0 @@
|
|||
module.exports = {
|
||||
encode: string => Buffer.from(string),
|
||||
decode: buffer => buffer.toString('utf8')
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -1,39 +1,43 @@
|
|||
var { promisify } = require('es6-promisify');
|
||||
'use strict';
|
||||
|
||||
var isNullPath = require('../path.js').isNull;
|
||||
var nop = require('../shared.js').nop;
|
||||
const { promisify } = require('es6-promisify');
|
||||
|
||||
var Constants = require('../constants.js');
|
||||
var FILE_SYSTEM_NAME = Constants.FILE_SYSTEM_NAME;
|
||||
var FS_FORMAT = Constants.FS_FORMAT;
|
||||
var FS_READY = Constants.FS_READY;
|
||||
var FS_PENDING = Constants.FS_PENDING;
|
||||
var FS_ERROR = Constants.FS_ERROR;
|
||||
var FS_NODUPEIDCHECK = Constants.FS_NODUPEIDCHECK;
|
||||
const Path = require('../path.js');
|
||||
|
||||
var providers = require('../providers/index.js');
|
||||
const providers = require('../providers/index.js');
|
||||
|
||||
var Shell = require('../shell/shell.js');
|
||||
var Intercom = require('../../lib/intercom.js');
|
||||
var FSWatcher = require('../fs-watcher.js');
|
||||
var Errors = require('../errors.js');
|
||||
var defaultGuidFn = require('../shared.js').guid;
|
||||
const Shell = require('../shell/shell.js');
|
||||
const Intercom = require('../../lib/intercom.js');
|
||||
const FSWatcher = require('../fs-watcher.js');
|
||||
const Errors = require('../errors.js');
|
||||
const {
|
||||
nop,
|
||||
guid: defaultGuidFn
|
||||
} = require('../shared.js');
|
||||
|
||||
var STDIN = Constants.STDIN;
|
||||
var STDOUT = Constants.STDOUT;
|
||||
var STDERR = Constants.STDERR;
|
||||
var FIRST_DESCRIPTOR = Constants.FIRST_DESCRIPTOR;
|
||||
const {
|
||||
fsConstants,
|
||||
FILE_SYSTEM_NAME,
|
||||
FS_FORMAT,
|
||||
FS_READY,
|
||||
FS_PENDING,
|
||||
FS_ERROR,
|
||||
FS_NODUPEIDCHECK,
|
||||
STDIN,
|
||||
STDOUT,
|
||||
STDERR
|
||||
} = require('../constants.js');
|
||||
|
||||
// The core fs operations live on impl
|
||||
var impl = require('./implementation.js');
|
||||
const impl = require('./implementation.js');
|
||||
|
||||
// node.js supports a calling pattern that leaves off a callback.
|
||||
function maybeCallback(callback) {
|
||||
if(typeof callback === 'function') {
|
||||
if (typeof callback === 'function') {
|
||||
return callback;
|
||||
}
|
||||
return function(err) {
|
||||
if(err) {
|
||||
return function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
@ -41,11 +45,66 @@ function maybeCallback(callback) {
|
|||
|
||||
// Default callback that logs an error if passed in
|
||||
function defaultCallback(err) {
|
||||
if(err) {
|
||||
if (err) {
|
||||
/* eslint no-console: 0 */
|
||||
console.error('Filer error: ', err);
|
||||
}
|
||||
}
|
||||
// Get a path (String) from a file:// URL. Support URL() like objects
|
||||
// https://github.com/nodejs/node/blob/968e901aff38a343b1de4addebf79fd8fa991c59/lib/internal/url.js#L1381
|
||||
function toPathIfFileURL(fileURLOrPath) {
|
||||
if (!(fileURLOrPath &&
|
||||
fileURLOrPath.protocol &&
|
||||
fileURLOrPath.pathname)) {
|
||||
return fileURLOrPath;
|
||||
}
|
||||
|
||||
if (fileURLOrPath.protocol !== 'file:') {
|
||||
throw new Errors.EINVAL('only file: URLs are supported for paths', fileURLOrPath);
|
||||
}
|
||||
|
||||
const pathname = fileURLOrPath.pathname;
|
||||
for (let n = 0; n < pathname.length; n++) {
|
||||
if (pathname[n] === '%') {
|
||||
const third = pathname.codePointAt(n + 2) | 0x20;
|
||||
if (pathname[n + 1] === '2' && third === 102) {
|
||||
throw new Errors.EINVAL('file: URLs must not include encoded / characters', fileURLOrPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decodeURIComponent(pathname);
|
||||
}
|
||||
|
||||
// Allow Buffers for paths. Assumes we want UTF8.
|
||||
function toPathIfBuffer(bufferOrPath) {
|
||||
return Buffer.isBuffer(bufferOrPath) ? bufferOrPath.toString() : bufferOrPath;
|
||||
}
|
||||
|
||||
function validatePath(path, allowRelative) {
|
||||
if (!path) {
|
||||
return new Errors.EINVAL('Path must be a string', path);
|
||||
} else if (Path.isNull(path)) {
|
||||
return new Errors.EINVAL('Path must be a string without null bytes.', path);
|
||||
} else if (!allowRelative && !Path.isAbsolute(path)) {
|
||||
return new Errors.EINVAL('Path must be absolute.', path);
|
||||
}
|
||||
}
|
||||
|
||||
function processPathArg(args, idx, allowRelative) {
|
||||
let path = args[idx];
|
||||
path = toPathIfFileURL(path);
|
||||
path = toPathIfBuffer(path);
|
||||
|
||||
// Some methods specifically allow for rel paths (eg symlink with srcPath)
|
||||
let err = validatePath(path, allowRelative);
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Overwrite path arg with converted and validated path
|
||||
args[idx] = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* FileSystem
|
||||
|
@ -79,14 +138,14 @@ function FileSystem(options, callback) {
|
|||
options = options || {};
|
||||
callback = callback || defaultCallback;
|
||||
|
||||
var flags = options.flags || [];
|
||||
var guid = options.guid ? options.guid : defaultGuidFn;
|
||||
var provider = options.provider || new providers.Default(options.name || FILE_SYSTEM_NAME);
|
||||
const flags = options.flags || [];
|
||||
const guid = options.guid ? options.guid : defaultGuidFn;
|
||||
const provider = options.provider || new providers.Default(options.name || FILE_SYSTEM_NAME);
|
||||
// If we're given a provider, match its name unless we get an explicit name
|
||||
var name = options.name || provider.name;
|
||||
var forceFormatting = flags.includes(FS_FORMAT);
|
||||
const name = options.name || provider.name;
|
||||
const forceFormatting = flags.includes(FS_FORMAT);
|
||||
|
||||
var fs = this;
|
||||
const fs = this;
|
||||
fs.readyState = FS_PENDING;
|
||||
fs.name = name;
|
||||
fs.error = null;
|
||||
|
@ -96,35 +155,24 @@ function FileSystem(options, callback) {
|
|||
fs.stderr = STDERR;
|
||||
|
||||
// Expose Node's fs.constants to users
|
||||
fs.constants = Constants.fsConstants;
|
||||
fs.constants = fsConstants;
|
||||
// Node also forwards the access mode flags onto fs
|
||||
fs.F_OK = fsConstants.F_OK;
|
||||
fs.R_OK = fsConstants.R_OK;
|
||||
fs.W_OK = fsConstants.W_OK;
|
||||
fs.X_OK = fsConstants.X_OK;
|
||||
|
||||
// Expose Shell constructor
|
||||
this.Shell = Shell.bind(undefined, this);
|
||||
|
||||
// Safely expose the list of open files and file
|
||||
// descriptor management functions
|
||||
var openFiles = {};
|
||||
var nextDescriptor = FIRST_DESCRIPTOR;
|
||||
Object.defineProperty(this, 'openFiles', {
|
||||
get: function() { return openFiles; }
|
||||
});
|
||||
this.allocDescriptor = function(openFileDescription) {
|
||||
var fd = nextDescriptor ++;
|
||||
openFiles[fd] = openFileDescription;
|
||||
return fd;
|
||||
};
|
||||
this.releaseDescriptor = function(fd) {
|
||||
delete openFiles[fd];
|
||||
};
|
||||
|
||||
// Safely expose the operation queue
|
||||
var queue = [];
|
||||
this.queueOrRun = function(operation) {
|
||||
var error;
|
||||
let queue = [];
|
||||
this.queueOrRun = function (operation) {
|
||||
let error;
|
||||
|
||||
if(FS_READY === fs.readyState) {
|
||||
if (FS_READY === fs.readyState) {
|
||||
operation.call(fs);
|
||||
} else if(FS_ERROR === fs.readyState) {
|
||||
} else if (FS_ERROR === fs.readyState) {
|
||||
error = new Errors.EFILESYSTEMERROR('unknown error');
|
||||
} else {
|
||||
queue.push(operation);
|
||||
|
@ -133,25 +181,25 @@ function FileSystem(options, callback) {
|
|||
return error;
|
||||
};
|
||||
function runQueued() {
|
||||
queue.forEach(function(operation) {
|
||||
queue.forEach(function (operation) {
|
||||
operation.call(this);
|
||||
}.bind(fs));
|
||||
queue = null;
|
||||
}
|
||||
|
||||
// We support the optional `options` arg from node, but ignore it
|
||||
this.watch = function(filename, options, listener) {
|
||||
if(isNullPath(filename)) {
|
||||
this.watch = function (filename, options, listener) {
|
||||
if (Path.isNull(filename)) {
|
||||
throw new Error('Path must be a string without null bytes.');
|
||||
}
|
||||
if(typeof options === 'function') {
|
||||
if (typeof options === 'function') {
|
||||
listener = options;
|
||||
options = {};
|
||||
}
|
||||
options = options || {};
|
||||
listener = listener || nop;
|
||||
|
||||
var watcher = new FSWatcher();
|
||||
const watcher = new FSWatcher();
|
||||
watcher.start(filename, false, options.recursive);
|
||||
watcher.on('change', listener);
|
||||
|
||||
|
@ -160,24 +208,24 @@ function FileSystem(options, callback) {
|
|||
|
||||
// Deal with various approaches to node ID creation
|
||||
function wrappedGuidFn(context) {
|
||||
return function(callback) {
|
||||
return function (callback) {
|
||||
// Skip the duplicate ID check if asked to
|
||||
if(flags.includes(FS_NODUPEIDCHECK)) {
|
||||
if (flags.includes(FS_NODUPEIDCHECK)) {
|
||||
callback(null, guid());
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise (default) make sure this id is unused first
|
||||
function guidWithCheck(callback) {
|
||||
var id = guid();
|
||||
context.getObject(id, function(err, value) {
|
||||
if(err) {
|
||||
const id = guid();
|
||||
context.getObject(id, function (err, value) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// If this id is unused, use it, otherwise find another
|
||||
if(!value) {
|
||||
if (!value) {
|
||||
callback(null, id);
|
||||
} else {
|
||||
guidWithCheck(callback);
|
||||
|
@ -191,27 +239,28 @@ function FileSystem(options, callback) {
|
|||
// Let other instances (in this or other windows) know about
|
||||
// any changes to this fs instance.
|
||||
function broadcastChanges(changes) {
|
||||
if(!changes.length) {
|
||||
if (!changes.length) {
|
||||
return;
|
||||
}
|
||||
var intercom = Intercom.getInstance();
|
||||
changes.forEach(function(change) {
|
||||
const intercom = Intercom.getInstance();
|
||||
changes.forEach(function (change) {
|
||||
intercom.emit(change.event, change.path);
|
||||
});
|
||||
}
|
||||
|
||||
// Open file system storage provider
|
||||
provider.open(function(err) {
|
||||
provider.open(function (err) {
|
||||
function complete(error) {
|
||||
function wrappedContext(methodName) {
|
||||
var context = provider[methodName]();
|
||||
let context = provider[methodName]();
|
||||
context.name = name;
|
||||
context.flags = flags;
|
||||
context.changes = [];
|
||||
context.guid = wrappedGuidFn(context);
|
||||
|
||||
// When the context is finished, let the fs deal with any change events
|
||||
context.close = function() {
|
||||
var changes = context.changes;
|
||||
context.close = function () {
|
||||
let changes = context.changes;
|
||||
broadcastChanges(changes);
|
||||
changes.length = 0;
|
||||
};
|
||||
|
@ -224,15 +273,15 @@ function FileSystem(options, callback) {
|
|||
// for paths updated during the lifetime of the context). From this
|
||||
// point forward we won't call open again, so it's safe to drop it.
|
||||
fs.provider = {
|
||||
openReadWriteContext: function() {
|
||||
openReadWriteContext: function () {
|
||||
return wrappedContext('getReadWriteContext');
|
||||
},
|
||||
openReadOnlyContext: function() {
|
||||
openReadOnlyContext: function () {
|
||||
return wrappedContext('getReadOnlyContext');
|
||||
}
|
||||
};
|
||||
|
||||
if(error) {
|
||||
if (error) {
|
||||
fs.readyState = FS_ERROR;
|
||||
} else {
|
||||
fs.readyState = FS_READY;
|
||||
|
@ -241,18 +290,18 @@ function FileSystem(options, callback) {
|
|||
callback(error, fs);
|
||||
}
|
||||
|
||||
if(err) {
|
||||
if (err) {
|
||||
return complete(err);
|
||||
}
|
||||
|
||||
var context = provider.getReadWriteContext();
|
||||
const context = provider.getReadWriteContext();
|
||||
context.guid = wrappedGuidFn(context);
|
||||
|
||||
// Mount the filesystem, formatting if necessary
|
||||
if(forceFormatting) {
|
||||
if (forceFormatting) {
|
||||
// Wipe the storage provider, then write root block
|
||||
context.clear(function(err) {
|
||||
if(err) {
|
||||
context.clear(function (err) {
|
||||
if (err) {
|
||||
return complete(err);
|
||||
}
|
||||
impl.ensureRootDirectory(context, complete);
|
||||
|
@ -263,72 +312,91 @@ function FileSystem(options, callback) {
|
|||
}
|
||||
});
|
||||
FileSystem.prototype.promises = {};
|
||||
|
||||
/**
|
||||
* Public API for FileSystem. All node.js methods that are
|
||||
* exposed on fs.promises include `promise: true`. We also
|
||||
* include our own extra methods, but skip the fd versions
|
||||
* to match node.js, which puts these on a FileHandle object.
|
||||
* Public API for FileSystem. All node.js methods that are exposed on fs.promises
|
||||
* include `promise: true`. We also include our own extra methods, but skip the
|
||||
* fd versions to match node.js, which puts these on a `FileHandle` object.
|
||||
* Any method that deals with path argument(s) also includes the position of
|
||||
* those args in one of `absPathArgs: [...]` or `relPathArgs: [...]`, so they
|
||||
* can be processed and validated before being passed on to the method.
|
||||
*/
|
||||
[
|
||||
{ name: 'open', promises: true },
|
||||
{ name: 'access', promises: true },
|
||||
{ name: 'chmod', promises: true },
|
||||
{ name: 'fchmod' },
|
||||
{ name: 'chown', promises: true },
|
||||
{ name: 'fchown' },
|
||||
{ name: 'appendFile', promises: true, absPathArgs: [0] },
|
||||
{ name: 'access', promises: true, absPathArgs: [0] },
|
||||
{ name: 'chown', promises: true, absPathArgs: [0] },
|
||||
{ name: 'chmod', promises: true, absPathArgs: [0] },
|
||||
{ name: 'close' },
|
||||
{ name: 'mknod', promises: true },
|
||||
{ name: 'mkdir', promises: true },
|
||||
{ name: 'mkdtemp', promises: true },
|
||||
{ name: 'rmdir', promises: true },
|
||||
{ name: 'stat', promises: true },
|
||||
// copyFile - https://github.com/filerjs/filer/issues/436
|
||||
{ name: 'exists', absPathArgs: [0] },
|
||||
{ name: 'fchown' },
|
||||
{ name: 'fchmod' },
|
||||
// fdatasync - https://github.com/filerjs/filer/issues/653
|
||||
{ name: 'fgetxattr' },
|
||||
{ name: 'fremovexattr' },
|
||||
{ name: 'fsetxattr' },
|
||||
{ name: 'fstat' },
|
||||
{ name: 'fsync' },
|
||||
{ name: 'link', promises: true },
|
||||
{ name: 'unlink', promises: true },
|
||||
{ name: 'read' },
|
||||
{ name: 'readFile', promises: true },
|
||||
{ name: 'write' },
|
||||
{ name: 'writeFile', promises: true },
|
||||
{ name: 'appendFile', promises: true },
|
||||
{ name: 'exists' },
|
||||
{ name: 'lseek' },
|
||||
{ name: 'readdir', promises: true },
|
||||
{ name: 'rename', promises: true },
|
||||
{ name: 'readlink', promises: true },
|
||||
{ name: 'symlink', promises: true },
|
||||
{ name: 'lstat', promises: true },
|
||||
{ name: 'truncate', promises: true },
|
||||
{ name: 'ftruncate' },
|
||||
{ name: 'utimes', promises: true },
|
||||
{ name: 'futimes' },
|
||||
{ name: 'setxattr', promises: true },
|
||||
{ name: 'getxattr', promises: true },
|
||||
{ name: 'fsetxattr' },
|
||||
{ name: 'fgetxattr' },
|
||||
{ name: 'removexattr', promises: true },
|
||||
{ name: 'fremovexattr' }
|
||||
].forEach(function(method) {
|
||||
var methodName = method.name;
|
||||
var shouldPromisify = method.promises === true;
|
||||
{ name: 'getxattr', promises: true, absPathArgs: [0] },
|
||||
// lchown - https://github.com/filerjs/filer/issues/620
|
||||
// lchmod - https://github.com/filerjs/filer/issues/619
|
||||
{ name: 'link', promises: true, absPathArgs: [0, 1] },
|
||||
{ name: 'lseek' },
|
||||
{ name: 'lstat', promises: true },
|
||||
{ name: 'mkdir', promises: true, absPathArgs: [0] },
|
||||
{ name: 'mkdtemp', promises: true },
|
||||
{ name: 'mknod', promises: true, absPathArgs: [0] },
|
||||
{ name: 'open', promises: true, absPathArgs: [0] },
|
||||
{ name: 'readdir', promises: true, absPathArgs: [0] },
|
||||
{ name: 'read' },
|
||||
{ name: 'readFile', promises: true, absPathArgs: [0] },
|
||||
{ name: 'readlink', promises: true, absPathArgs: [0] },
|
||||
// realpath - https://github.com/filerjs/filer/issues/85
|
||||
{ name: 'removexattr', promises: true, absPathArgs: [0] },
|
||||
{ name: 'rename', promises: true, absPathArgs: [0, 1] },
|
||||
{ name: 'rmdir', promises: true, absPathArgs: [0] },
|
||||
{ name: 'setxattr', promises: true, absPathArgs: [0] },
|
||||
{ name: 'stat', promises: true, absPathArgs: [0] },
|
||||
{ name: 'symlink', promises: true, relPathArgs: [0], absPathArgs: [1] },
|
||||
{ name: 'truncate', promises: true, absPathArgs: [0] },
|
||||
// unwatchFile - https://github.com/filerjs/filer/pull/553
|
||||
{ name: 'unlink', promises: true, absPathArgs: [0] },
|
||||
{ name: 'utimes', promises: true, absPathArgs: [0] },
|
||||
// watch - implemented above in `this.watch`
|
||||
// watchFile - https://github.com/filerjs/filer/issues/654
|
||||
{ name: 'writeFile', promises: true, absPathArgs: [0] },
|
||||
{ name: 'write' }
|
||||
].forEach(function (method) {
|
||||
const methodName = method.name;
|
||||
const shouldPromisify = method.promises === true;
|
||||
|
||||
FileSystem.prototype[methodName] = function() {
|
||||
var fs = this;
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
var lastArgIndex = args.length - 1;
|
||||
FileSystem.prototype[methodName] = function () {
|
||||
const fs = this;
|
||||
const args = Array.prototype.slice.call(arguments, 0);
|
||||
const lastArgIndex = args.length - 1;
|
||||
|
||||
// We may or may not get a callback, and since node.js supports
|
||||
// fire-and-forget style fs operations, we have to dance a bit here.
|
||||
var missingCallback = typeof args[lastArgIndex] !== 'function';
|
||||
var callback = maybeCallback(args[lastArgIndex]);
|
||||
const missingCallback = typeof args[lastArgIndex] !== 'function';
|
||||
const callback = maybeCallback(args[lastArgIndex]);
|
||||
|
||||
var error = fs.queueOrRun(function() {
|
||||
var context = fs.provider.openReadWriteContext();
|
||||
// Deal with path arguments, validating and normalizing Buffer and file:// URLs
|
||||
if (method.absPathArgs) {
|
||||
method.absPathArgs.forEach(pathArg => processPathArg(args, pathArg, false));
|
||||
}
|
||||
if (method.relPathArgs) {
|
||||
method.relPathArgs.forEach(pathArg => processPathArg(args, pathArg, true));
|
||||
}
|
||||
|
||||
const error = fs.queueOrRun(function () {
|
||||
const context = fs.provider.openReadWriteContext();
|
||||
|
||||
// Fail early if the filesystem is in an error state (e.g.,
|
||||
// provider failed to open.
|
||||
if(FS_ERROR === fs.readyState) {
|
||||
var err = new Errors.EFILESYSTEMERROR('filesystem unavailable, operation canceled');
|
||||
if (FS_ERROR === fs.readyState) {
|
||||
const err = new Errors.EFILESYSTEMERROR('filesystem unavailable, operation canceled');
|
||||
return callback.call(fs, err);
|
||||
}
|
||||
|
||||
|
@ -339,7 +407,7 @@ function FileSystem(options, callback) {
|
|||
}
|
||||
|
||||
// Either add or replace the callback with our wrapper complete()
|
||||
if(missingCallback) {
|
||||
if (missingCallback) {
|
||||
args.push(complete);
|
||||
} else {
|
||||
args[lastArgIndex] = complete;
|
||||
|
@ -348,16 +416,16 @@ function FileSystem(options, callback) {
|
|||
// Forward this call to the impl's version, using the following
|
||||
// call signature, with complete() as the callback/last-arg now:
|
||||
// fn(fs, context, arg0, arg1, ... , complete);
|
||||
var fnArgs = [fs, context].concat(args);
|
||||
const fnArgs = [context].concat(args);
|
||||
impl[methodName].apply(null, fnArgs);
|
||||
});
|
||||
if(error) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Add to fs.promises if appropriate
|
||||
if(shouldPromisify) {
|
||||
if (shouldPromisify) {
|
||||
FileSystem.prototype.promises[methodName] = promisify(FileSystem.prototype[methodName].bind(fs));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
var EventEmitter = require('../lib/eventemitter.js');
|
||||
var Path = require('./path.js');
|
||||
var Intercom = require('../lib/intercom.js');
|
||||
'using strict';
|
||||
|
||||
const EventEmitter = require('../lib/eventemitter.js');
|
||||
const Path = require('./path.js');
|
||||
const Intercom = require('../lib/intercom.js');
|
||||
|
||||
/**
|
||||
* FSWatcher based on node.js' FSWatcher
|
||||
|
@ -8,10 +10,10 @@ var Intercom = require('../lib/intercom.js');
|
|||
*/
|
||||
function FSWatcher() {
|
||||
EventEmitter.call(this);
|
||||
var self = this;
|
||||
var recursive = false;
|
||||
var recursivePathPrefix;
|
||||
var filename;
|
||||
const self = this;
|
||||
let recursive = false;
|
||||
let recursivePathPrefix;
|
||||
let filename;
|
||||
|
||||
function onchange(path) {
|
||||
// Watch for exact filename, or parent path when recursive is true.
|
||||
|
@ -46,12 +48,12 @@ function FSWatcher() {
|
|||
recursivePathPrefix = filename === '/' ? '/' : filename + '/';
|
||||
}
|
||||
|
||||
var intercom = Intercom.getInstance();
|
||||
const intercom = Intercom.getInstance();
|
||||
intercom.on('change', onchange);
|
||||
};
|
||||
|
||||
self.close = function() {
|
||||
var intercom = Intercom.getInstance();
|
||||
const intercom = Intercom.getInstance();
|
||||
intercom.off('change', onchange);
|
||||
self.removeAllListeners('change');
|
||||
};
|
||||
|
|
31
src/index.js
31
src/index.js
|
@ -1,7 +1,34 @@
|
|||
module.exports = {
|
||||
let fs = null;
|
||||
let Filer = null;
|
||||
|
||||
module.exports = Filer = {
|
||||
FileSystem: require('./filesystem/interface.js'),
|
||||
Buffer: Buffer,
|
||||
// We previously called this Path, but node calls it path. Do both
|
||||
Path: require('./path.js'),
|
||||
path: require('./path.js'),
|
||||
Errors: require('./errors.js'),
|
||||
Shell: require('./shell/shell.js')
|
||||
Shell: require('./shell/shell.js'),
|
||||
/**
|
||||
* @deprecated Importing filer from your webpack config is not recommended.
|
||||
*
|
||||
* The filer `FilerWebpackPlugin` class is exposed directly.
|
||||
*
|
||||
* ```
|
||||
* const { FilerWebpackPlugin } = require('filer/webpack');
|
||||
* ```
|
||||
*/
|
||||
FilerWebpackPlugin: require('./webpack-plugin'),
|
||||
};
|
||||
|
||||
// Add a getter for the `fs` instance, which returns
|
||||
// a Filer FileSystem instance, using the default provider/flags.
|
||||
Object.defineProperty(Filer, 'fs', {
|
||||
enumerable: true,
|
||||
get() {
|
||||
if(!fs) {
|
||||
fs = new Filer.FileSystem();
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
const { FIRST_DESCRIPTOR } = require('./constants');
|
||||
const openFiles = {};
|
||||
|
||||
/**
|
||||
* Start at FIRST_DESCRIPTOR and go until we find
|
||||
* an empty file descriptor, then return it.
|
||||
*/
|
||||
const getEmptyDescriptor = () => {
|
||||
let fd = FIRST_DESCRIPTOR;
|
||||
|
||||
while(getOpenFileDescription(fd)) {
|
||||
fd++;
|
||||
}
|
||||
|
||||
return fd;
|
||||
};
|
||||
|
||||
/**
|
||||
* Look up the open file description object for a given
|
||||
* file descriptor.
|
||||
*/
|
||||
const getOpenFileDescription = ofd => openFiles[ofd];
|
||||
|
||||
/**
|
||||
* Allocate a new file descriptor for the given
|
||||
* open file description.
|
||||
*/
|
||||
const allocDescriptor = openFileDescription => {
|
||||
const ofd = getEmptyDescriptor();
|
||||
openFiles[ofd] = openFileDescription;
|
||||
return ofd;
|
||||
};
|
||||
|
||||
/**
|
||||
* Release the given existing file descriptor created
|
||||
* with allocDescriptor().
|
||||
*/
|
||||
const releaseDescriptor = ofd => delete openFiles[ofd];
|
||||
|
||||
module.exports = {
|
||||
allocDescriptor,
|
||||
releaseDescriptor,
|
||||
getOpenFileDescription
|
||||
};
|
|
@ -10,7 +10,7 @@ process.cwd = () => '/';
|
|||
* a few things we need for the browser environment.
|
||||
*/
|
||||
const nodePath = require('path');
|
||||
const filerPath = Object.create(nodePath);
|
||||
const filerPath = Object.assign({}, nodePath);
|
||||
|
||||
/**
|
||||
* Patch path.basename() to return / vs. ''
|
||||
|
|
|
@ -1,35 +1,8 @@
|
|||
var IndexedDB = require('./indexeddb.js');
|
||||
var WebSQL = require('./websql.js');
|
||||
var Memory = require('./memory.js');
|
||||
const IndexedDB = require('./indexeddb.js');
|
||||
const Memory = require('./memory.js');
|
||||
|
||||
module.exports = {
|
||||
IndexedDB: IndexedDB,
|
||||
WebSQL: WebSQL,
|
||||
Memory: Memory,
|
||||
|
||||
/**
|
||||
* Convenience Provider references
|
||||
*/
|
||||
|
||||
// The default provider to use when none is specified
|
||||
Default: IndexedDB,
|
||||
|
||||
// The Fallback provider does automatic fallback checks
|
||||
Fallback: (function() {
|
||||
if(IndexedDB.isSupported()) {
|
||||
return IndexedDB;
|
||||
}
|
||||
|
||||
if(WebSQL.isSupported()) {
|
||||
return WebSQL;
|
||||
}
|
||||
|
||||
function NotSupported() {
|
||||
throw '[Filer Error] Your browser doesn\'t support IndexedDB or WebSQL.';
|
||||
}
|
||||
NotSupported.isSupported = function() {
|
||||
return false;
|
||||
};
|
||||
return NotSupported;
|
||||
}())
|
||||
Memory: Memory
|
||||
};
|
||||
|
|
|
@ -3,11 +3,6 @@ var FILE_STORE_NAME = require('../constants.js').FILE_STORE_NAME;
|
|||
var IDB_RW = require('../constants.js').IDB_RW;
|
||||
var IDB_RO = require('../constants.js').IDB_RO;
|
||||
|
||||
var indexedDB = global.indexedDB ||
|
||||
global.mozIndexedDB ||
|
||||
global.webkitIndexedDB ||
|
||||
global.msIndexedDB;
|
||||
|
||||
function IndexedDBContext(db, mode) {
|
||||
this.db = db;
|
||||
this.mode = mode;
|
||||
|
@ -114,6 +109,10 @@ function IndexedDB(name) {
|
|||
this.db = null;
|
||||
}
|
||||
IndexedDB.isSupported = function() {
|
||||
var indexedDB = global.indexedDB ||
|
||||
global.mozIndexedDB ||
|
||||
global.webkitIndexedDB ||
|
||||
global.msIndexedDB;
|
||||
return !!indexedDB;
|
||||
};
|
||||
|
||||
|
@ -126,6 +125,11 @@ IndexedDB.prototype.open = function(callback) {
|
|||
}
|
||||
|
||||
try {
|
||||
var indexedDB = global.indexedDB ||
|
||||
global.mozIndexedDB ||
|
||||
global.webkitIndexedDB ||
|
||||
global.msIndexedDB;
|
||||
|
||||
// NOTE: we're not using versioned databases.
|
||||
var openRequest = indexedDB.open(that.name);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ var asyncCallback = require('../../lib/async.js').setImmediate;
|
|||
var createDB = (function() {
|
||||
var pool = {};
|
||||
return function getOrCreate(name) {
|
||||
if(!pool.hasOwnProperty(name)) {
|
||||
if(!Object.prototype.hasOwnProperty.call(pool, name)) {
|
||||
pool[name] = {};
|
||||
}
|
||||
return pool[name];
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
var FILE_SYSTEM_NAME = require('../constants.js').FILE_SYSTEM_NAME;
|
||||
var FILE_STORE_NAME = require('../constants.js').FILE_STORE_NAME;
|
||||
var WSQL_VERSION = require('../constants.js').WSQL_VERSION;
|
||||
var WSQL_SIZE = require('../constants.js').WSQL_SIZE;
|
||||
var WSQL_DESC = require('../constants.js').WSQL_DESC;
|
||||
var Errors = require('../errors.js');
|
||||
var base64ArrayBuffer = require('base64-arraybuffer');
|
||||
|
||||
function WebSQLContext(db, isReadOnly) {
|
||||
var that = this;
|
||||
this.getTransaction = function(callback) {
|
||||
if(that.transaction) {
|
||||
callback(that.transaction);
|
||||
return;
|
||||
}
|
||||
// Either do readTransaction() (read-only) or transaction() (read/write)
|
||||
db[isReadOnly ? 'readTransaction' : 'transaction'](function(transaction) {
|
||||
that.transaction = transaction;
|
||||
callback(transaction);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
WebSQLContext.prototype.clear = function(callback) {
|
||||
function onError(transaction, error) {
|
||||
callback(error);
|
||||
}
|
||||
function onSuccess() {
|
||||
callback(null);
|
||||
}
|
||||
this.getTransaction(function(transaction) {
|
||||
transaction.executeSql('DELETE FROM ' + FILE_STORE_NAME + ';',
|
||||
[], onSuccess, onError);
|
||||
});
|
||||
};
|
||||
|
||||
function _get(getTransaction, key, callback) {
|
||||
function onSuccess(transaction, result) {
|
||||
// If the key isn't found, return null
|
||||
var value = result.rows.length === 0 ? null : result.rows.item(0).data;
|
||||
callback(null, value);
|
||||
}
|
||||
function onError(transaction, error) {
|
||||
callback(error);
|
||||
}
|
||||
getTransaction(function(transaction) {
|
||||
transaction.executeSql('SELECT data FROM ' + FILE_STORE_NAME + ' WHERE id = ? LIMIT 1;',
|
||||
[key], onSuccess, onError);
|
||||
});
|
||||
}
|
||||
WebSQLContext.prototype.getObject = function(key, callback) {
|
||||
_get(this.getTransaction, key, function(err, result) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
try {
|
||||
if(result) {
|
||||
result = JSON.parse(result);
|
||||
}
|
||||
} catch(e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
callback(null, result);
|
||||
});
|
||||
};
|
||||
WebSQLContext.prototype.getBuffer = function(key, callback) {
|
||||
_get(this.getTransaction, key, function(err, result) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// Deal with zero-length ArrayBuffers, which will be encoded as ''
|
||||
if(result || result === '') {
|
||||
var arrayBuffer = base64ArrayBuffer.decode(result);
|
||||
result = Buffer.from(arrayBuffer);
|
||||
}
|
||||
|
||||
callback(null, result);
|
||||
});
|
||||
};
|
||||
|
||||
function _put(getTransaction, key, value, callback) {
|
||||
function onSuccess() {
|
||||
callback(null);
|
||||
}
|
||||
function onError(transaction, error) {
|
||||
callback(error);
|
||||
}
|
||||
getTransaction(function(transaction) {
|
||||
transaction.executeSql('INSERT OR REPLACE INTO ' + FILE_STORE_NAME + ' (id, data) VALUES (?, ?);',
|
||||
[key, value], onSuccess, onError);
|
||||
});
|
||||
}
|
||||
WebSQLContext.prototype.putObject = function(key, value, callback) {
|
||||
var json = JSON.stringify(value);
|
||||
_put(this.getTransaction, key, json, callback);
|
||||
};
|
||||
WebSQLContext.prototype.putBuffer = function(key, uint8BackedBuffer, callback) {
|
||||
var base64 = base64ArrayBuffer.encode(uint8BackedBuffer.buffer);
|
||||
_put(this.getTransaction, key, base64, callback);
|
||||
};
|
||||
|
||||
WebSQLContext.prototype.delete = function(key, callback) {
|
||||
function onSuccess() {
|
||||
callback(null);
|
||||
}
|
||||
function onError(transaction, error) {
|
||||
callback(error);
|
||||
}
|
||||
this.getTransaction(function(transaction) {
|
||||
transaction.executeSql('DELETE FROM ' + FILE_STORE_NAME + ' WHERE id = ?;',
|
||||
[key], onSuccess, onError);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
function WebSQL(name) {
|
||||
this.name = name || FILE_SYSTEM_NAME;
|
||||
this.db = null;
|
||||
}
|
||||
WebSQL.isSupported = function() {
|
||||
return !!global.openDatabase;
|
||||
};
|
||||
|
||||
WebSQL.prototype.open = function(callback) {
|
||||
var that = this;
|
||||
|
||||
// Bail if we already have a db open
|
||||
if(that.db) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
var db = global.openDatabase(that.name, WSQL_VERSION, WSQL_DESC, WSQL_SIZE);
|
||||
if(!db) {
|
||||
callback('[WebSQL] Unable to open database.');
|
||||
return;
|
||||
}
|
||||
|
||||
function onError(transaction, error) {
|
||||
if (error.code === 5) {
|
||||
callback(new Errors.EINVAL('WebSQL cannot be accessed. If private browsing is enabled, disable it.'));
|
||||
}
|
||||
callback(error);
|
||||
}
|
||||
function onSuccess() {
|
||||
that.db = db;
|
||||
callback();
|
||||
}
|
||||
|
||||
// Create the table and index we'll need to store the fs data.
|
||||
db.transaction(function(transaction) {
|
||||
function createIndex(transaction) {
|
||||
transaction.executeSql('CREATE INDEX IF NOT EXISTS idx_' + FILE_STORE_NAME + '_id' +
|
||||
' on ' + FILE_STORE_NAME + ' (id);',
|
||||
[], onSuccess, onError);
|
||||
}
|
||||
transaction.executeSql('CREATE TABLE IF NOT EXISTS ' + FILE_STORE_NAME + ' (id unique, data TEXT);',
|
||||
[], createIndex, onError);
|
||||
});
|
||||
};
|
||||
WebSQL.prototype.getReadOnlyContext = function() {
|
||||
return new WebSQLContext(this.db, true);
|
||||
};
|
||||
WebSQL.prototype.getReadWriteContext = function() {
|
||||
return new WebSQLContext(this.db, false);
|
||||
};
|
||||
|
||||
module.exports = WebSQL;
|
|
@ -1,4 +1,5 @@
|
|||
var defaults = require('../constants.js').ENVIRONMENT;
|
||||
'use strict';
|
||||
const defaults = require('../constants.js').ENVIRONMENT;
|
||||
|
||||
module.exports = function Environment(env) {
|
||||
env = env || {};
|
||||
|
|
|
@ -387,7 +387,8 @@ Shell.prototype.mkdirp = function(path, callback) {
|
|||
callback(new Errors.EINVAL('Missing path argument'));
|
||||
return;
|
||||
}
|
||||
else if (path === '/') {
|
||||
path = Path.resolve(sh.pwd(), path);
|
||||
if (path === '/') {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
|
19
src/stats.js
19
src/stats.js
|
@ -1,9 +1,10 @@
|
|||
var Constants = require('./constants.js');
|
||||
var Path = require('./path.js');
|
||||
'use strict';
|
||||
|
||||
// https://github.com/nodejs/node/blob/4f1297f259b09d129ac01afbd4c674263b7ac124/lib/internal/fs/utils.js#L231
|
||||
function dateFromNumeric(num) {
|
||||
return new Date(Number(num) * 1000);
|
||||
const Constants = require('./constants.js');
|
||||
const Path = require('./path.js');
|
||||
|
||||
function dateFromMs(ms) {
|
||||
return new Date(Number(ms));
|
||||
}
|
||||
|
||||
function Stats(path, fileNode, devName) {
|
||||
|
@ -13,10 +14,10 @@ function Stats(path, fileNode, devName) {
|
|||
this.size = fileNode.size;
|
||||
this.nlinks = fileNode.nlinks;
|
||||
// Date objects
|
||||
this.atime = dateFromNumeric(fileNode.atime);
|
||||
this.mtime = dateFromNumeric(fileNode.mtime);
|
||||
this.ctime = dateFromNumeric(fileNode.ctime);
|
||||
// Unix timestamp Numbers
|
||||
this.atime = dateFromMs(fileNode.atime);
|
||||
this.mtime = dateFromMs(fileNode.mtime);
|
||||
this.ctime = dateFromMs(fileNode.ctime);
|
||||
// Unix timestamp MS Numbers
|
||||
this.atimeMs = fileNode.atime;
|
||||
this.mtimeMs = fileNode.mtime;
|
||||
this.ctimeMs = fileNode.ctime;
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
var path = require('path');
|
||||
var utils = require('./utils');
|
||||
|
||||
const PLUGIN_NAME = 'filer-webpack-plugin';
|
||||
|
||||
const OPTIONS_SCHEMA = require('./schema');
|
||||
const OPTIONS_PROCESSORS = require('./processors');
|
||||
|
||||
module.exports = class FilerWebpackPlugin {
|
||||
|
||||
constructor(options = {}) {
|
||||
utils.validateOptions(options, OPTIONS_SCHEMA);
|
||||
this.options = utils.processOptions(options, OPTIONS_PROCESSORS);
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.hooks.normalModuleFactory.tap(
|
||||
PLUGIN_NAME,
|
||||
(factory) => {
|
||||
factory.hooks.resolve.tap(
|
||||
PLUGIN_NAME,
|
||||
(resolveData) => {
|
||||
// Resolve fsProvider if required
|
||||
if (
|
||||
resolveData.request === 'fsProvider'
|
||||
&& resolveData.context === this.options.shimsDir
|
||||
) {
|
||||
return this.resolveFsProvider(resolveData);
|
||||
}
|
||||
|
||||
// Ignore filer files (these should resolve modules normally)
|
||||
if (resolveData.context.startsWith(this.options.filerDir)) return;
|
||||
|
||||
// Apply fs, path and buffer shims if required
|
||||
switch (resolveData.request) {
|
||||
case 'fs':
|
||||
if (!this.options.shimFs) return;
|
||||
return this.applyFsShim(resolveData);
|
||||
case 'path':
|
||||
if (!this.options.shimPath) return;
|
||||
return this.applyPathShim(resolveData);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
resolveFsProvider(resolveData) {
|
||||
switch (this.options.fsProvider) {
|
||||
case 'default':
|
||||
resolveData.request = path.join(this.options.fsProviderDir, 'default.js');
|
||||
break;
|
||||
case 'indexeddb':
|
||||
resolveData.request = path.join(this.options.fsProviderDir, 'indexeddb.js');
|
||||
break;
|
||||
case 'memory':
|
||||
resolveData.request = path.join(this.options.fsProviderDir, 'memory.js');
|
||||
break;
|
||||
case 'custom':
|
||||
resolveData.request = path.join(this.options.fsProviderDir, 'custom.js');
|
||||
break;
|
||||
default:
|
||||
throw new Error([
|
||||
'Invalid option for fsProvider.',
|
||||
'fsProvider must be one of \'default\', \'indexeddb\', \'memory\' or \'custom\'.',
|
||||
'If using a custom fsProvider, you must also provide the fsProviderDir option.'
|
||||
].join(' '));
|
||||
}
|
||||
}
|
||||
|
||||
applyFsShim(resolveData) {
|
||||
resolveData.request = path.join(this.options.shimsDir, 'fs.js');
|
||||
}
|
||||
|
||||
applyPathShim(resolveData) {
|
||||
resolveData.request = path.join(this.options.shimsDir, 'path.js');
|
||||
}
|
||||
};
|
|
@ -0,0 +1,34 @@
|
|||
var path = require('path');
|
||||
|
||||
const ROOT_DIR_TAG = '<rootDir>';
|
||||
const CWD = process.cwd();
|
||||
|
||||
module.exports = {
|
||||
filerDir: {
|
||||
process: function(value) {
|
||||
if (!value) {
|
||||
return path.join(CWD, 'node_modules', 'filer');
|
||||
}
|
||||
return path.resolve(value.replace(ROOT_DIR_TAG, CWD));
|
||||
},
|
||||
},
|
||||
shimsDir: {
|
||||
process: function(value) {
|
||||
if (!value) {
|
||||
return path.join(CWD, 'node_modules', 'filer', 'shims');
|
||||
}
|
||||
return path.resolve(value.replace(ROOT_DIR_TAG, CWD));
|
||||
}
|
||||
},
|
||||
fsProviderDir: {
|
||||
process: function(value) {
|
||||
if (!value) {
|
||||
return path.join(CWD, 'node_modules', 'filer', 'shims', 'providers');
|
||||
}
|
||||
return path.resolve(value.replace(ROOT_DIR_TAG, CWD));
|
||||
},
|
||||
},
|
||||
shimFs: { default: true },
|
||||
shimPath: { default: true},
|
||||
fsProvider: { default: 'default'},
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
module.exports = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
filerDir: {
|
||||
type: 'string',
|
||||
},
|
||||
shimsDir: {
|
||||
type: 'string',
|
||||
},
|
||||
shimFs: {
|
||||
type: 'boolean',
|
||||
},
|
||||
shimPath: {
|
||||
type: 'boolean',
|
||||
},
|
||||
fsProvider: {
|
||||
type: 'string',
|
||||
},
|
||||
fsProviderDir: {
|
||||
type: 'string',
|
||||
},
|
||||
}
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
var { validate } = require('schema-utils');
|
||||
|
||||
function validateOptions(options, schema) {
|
||||
validate(schema, options);
|
||||
}
|
||||
|
||||
function processOptions(options, processors) {
|
||||
const processedOptions = {};
|
||||
|
||||
for (const [property, processor] of Object.entries(processors)) {
|
||||
processedOptions[property] = options[property];
|
||||
if (processedOptions[property] === undefined) {
|
||||
processedOptions[property] = processor.default;
|
||||
}
|
||||
if (processor.process) {
|
||||
processedOptions[property] = processor.process(processedOptions[property]);
|
||||
}
|
||||
}
|
||||
|
||||
return processedOptions;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
validateOptions,
|
||||
processOptions,
|
||||
};
|
|
@ -5,23 +5,15 @@ describe('undefined and relative paths, issue270', function() {
|
|||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should fail with EINVAL when called on an undefined path', function(done) {
|
||||
it('should fail with EINVAL when called on an undefined path', function() {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.writeFile(undefined, 'data', function(err) {
|
||||
expect(err).to.exist;
|
||||
expect(err.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
var fn = () => fs.writeFile(undefined, 'data');
|
||||
expect(fn).to.throw();
|
||||
});
|
||||
|
||||
it('should fail with EINVAL when called on a relative path', function(done) {
|
||||
it('should fail with EINVAL when called on a relative path', function() {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.writeFile('relpath/file.txt', 'data', function(err) {
|
||||
expect(err).to.exist;
|
||||
expect(err.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
var fn = () => fs.writeFile('relpath/file.txt', 'data');
|
||||
expect(fn).to.throw();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
'use strict';
|
||||
const util = require('../lib/test-utils.js');
|
||||
|
||||
describe('unexpected failures when calling fs functions (e.g. writeFile) with empty options object, issue 773', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should call fs.writeFile with an empty options object', function(done) {
|
||||
const fs = util.fs();
|
||||
fs.writeFile('/a', 'trololol', {}, done);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,115 @@
|
|||
'use strict';
|
||||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
|
||||
describe('fs.readdir fails when passing options, issue775', function () {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
function setup(fs, dir, cb) {
|
||||
fs.mkdir(dir, undefined, (err) => {
|
||||
if (err) {
|
||||
cb(err);
|
||||
}
|
||||
else {
|
||||
fs.writeFile(dir + '/file', '', (err) => {
|
||||
if (err) {
|
||||
cb(err);
|
||||
}
|
||||
else {
|
||||
fs.mkdir(dir + '/folder', (err) => {
|
||||
if (err) {
|
||||
cb(err);
|
||||
}
|
||||
else {
|
||||
fs.symlink(dir + '/file', dir + '/symlink', (err) => {
|
||||
if (err) {
|
||||
cb(err);
|
||||
}
|
||||
else {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
it('should create a directory, add a file, folder and symbolic link then call fs.readdir with buffer encoding', function (done) {
|
||||
var fs = util.fs();
|
||||
setup(fs, '/test_dir', (err) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
}
|
||||
fs.readdir('/test_dir', 'buffer', (err, data) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
}
|
||||
else {
|
||||
expect(data).to.have.length(3);
|
||||
|
||||
expect(data[0].toString()).to.equal('file');
|
||||
expect(data[1].toString()).to.equal('folder');
|
||||
expect(data[2].toString()).to.equal('symlink');
|
||||
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a directory, add a file, folder and symbolic link then call fs.readdir with withFileTypes and encoding options', function (done) {
|
||||
var fs = util.fs();
|
||||
setup(fs, '/test_dir', (err) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
}
|
||||
fs.readdir('/test_dir', { encoding: 'base64', withFileTypes: true }, (err, data) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
}
|
||||
else {
|
||||
expect(data).to.have.length(3);
|
||||
|
||||
expect(Buffer.from(data[0].name, 'base64').toString()).to.equal('file');
|
||||
expect(Buffer.from(data[1].name, 'base64').toString()).to.equal('folder');
|
||||
expect(Buffer.from(data[2].name, 'base64').toString()).to.equal('symlink');
|
||||
|
||||
expect(data[0].isFile()).to.be.true;
|
||||
expect(data[1].isDirectory()).to.be.true;
|
||||
expect(data[2].isSymbolicLink()).to.be.true;
|
||||
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a directory then call fs.readdir without options', function (done) {
|
||||
var fs = util.fs();
|
||||
setup(fs, '/test_dir', (err) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
}
|
||||
else {
|
||||
fs.readdir('/test_dir', (err, data) => {
|
||||
if (err) {
|
||||
done(err);
|
||||
}
|
||||
else {
|
||||
expect(data).to.have.length(3);
|
||||
|
||||
expect(data[0]).to.equal('file');
|
||||
expect(data[1]).to.equal('folder');
|
||||
expect(data[2]).to.equal('symlink');
|
||||
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
'use strict';
|
||||
const util = require('../lib/test-utils.js');
|
||||
|
||||
describe('fs.mkdir does not recursively create parent directories when called with { recursive: true }, issue776', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it.skip('should not throw when calling fs.mkdir with recursive flag set', function(done) {
|
||||
const fs = util.fs();
|
||||
fs.mkdir('/test_dir/a/b', { recursive: true }, done);
|
||||
});
|
||||
});
|
|
@ -5,3 +5,5 @@ generate them:
|
|||
|
||||
1. `tiny-fs.0.43.json` was created from `tests/filesystem/tiny-fs/` with https://github.com/filerjs/filer/blob/d66114e20c7f0235698d9933dbd90217ba86fa4e/dist/filer.min.js
|
||||
|
||||
If you need to create a new image, use `tools/get-filer-version.js` to
|
||||
get a specific version of Filer, then `tools/fs-image.js` to generate an image.
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<script src="../node_modules/mocha/mocha.js"></script>
|
||||
|
||||
<script>
|
||||
mocha.setup('bdd').timeout(5000).slow(250);
|
||||
mocha.setup('bdd').timeout(10000).slow(250);
|
||||
|
||||
window.onload = function() {
|
||||
mocha.checkLeaks();
|
||||
|
|
|
@ -3,6 +3,13 @@
|
|||
* get them running by default.
|
||||
*/
|
||||
|
||||
// Shims
|
||||
require('./spec/shims/fs.spec');
|
||||
require('./spec/shims/path.spec');
|
||||
|
||||
// Webpack Plugin
|
||||
require('./spec/webpack-plugin/webpack-plugin.spec');
|
||||
|
||||
// Filer
|
||||
require('./spec/filer.spec');
|
||||
require('./spec/filer.buffer.spec.js');
|
||||
|
@ -36,7 +43,6 @@ require('./spec/fs.truncate.spec');
|
|||
require('./spec/fs.ftruncate.spec');
|
||||
require('./spec/fs.utimes.spec');
|
||||
require('./spec/fs.xattr.spec');
|
||||
require('./spec/fs.stats.spec');
|
||||
require('./spec/path-resolution.spec');
|
||||
require('./spec/trailing-slashes.spec');
|
||||
require('./spec/times.spec');
|
||||
|
@ -52,7 +58,6 @@ require('./spec/fs.copyFile.spec');
|
|||
// Filer.FileSystem.providers.*
|
||||
require('./spec/providers/providers.spec');
|
||||
require('./spec/providers/providers.indexeddb.spec');
|
||||
require('./spec/providers/providers.websql.spec');
|
||||
require('./spec/providers/providers.memory.spec');
|
||||
require('./spec/providers/serializable-memory-provider.spec');
|
||||
|
||||
|
@ -86,3 +91,9 @@ require('./bugs/issue267.js');
|
|||
require('./bugs/issue270.js');
|
||||
require('./bugs/rename-dir-trailing-slash.js');
|
||||
require('./bugs/issue357.js');
|
||||
require('./bugs/issue773.js');
|
||||
require('./bugs/issue775.js');
|
||||
require('./bugs/issue776.js');
|
||||
|
||||
// Sample code from README
|
||||
require('./spec/readme.example.spec');
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
var Filer = require('../../src');
|
||||
'use strict';
|
||||
|
||||
var indexedDB = global.indexedDB ||
|
||||
global.mozIndexedDB ||
|
||||
global.webkitIndexedDB ||
|
||||
global.msIndexedDB;
|
||||
const Filer = require('../../src');
|
||||
|
||||
var needsCleanup = [];
|
||||
let needsCleanup = [];
|
||||
if(global.addEventListener) {
|
||||
global.addEventListener('beforeunload', function() {
|
||||
needsCleanup.forEach(function(f) { f(); });
|
||||
|
@ -13,8 +10,8 @@ if(global.addEventListener) {
|
|||
}
|
||||
|
||||
function IndexedDBTestProvider(name) {
|
||||
var _done = false;
|
||||
var that = this;
|
||||
let _done = false;
|
||||
let that = this;
|
||||
|
||||
function cleanup(callback) {
|
||||
callback = callback || function(){};
|
||||
|
@ -36,7 +33,12 @@ function IndexedDBTestProvider(name) {
|
|||
that.provider.db.close();
|
||||
}
|
||||
|
||||
var request = indexedDB.deleteDatabase(name);
|
||||
const indexedDB = global.indexedDB ||
|
||||
global.mozIndexedDB ||
|
||||
global.webkitIndexedDB ||
|
||||
global.msIndexedDB;
|
||||
|
||||
let request = indexedDB.deleteDatabase(name);
|
||||
request.onsuccess = finished;
|
||||
request.onerror = finished;
|
||||
} catch(e) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
var Filer = require('../../src');
|
||||
var IndexedDBTestProvider = require('./indexeddb.js');
|
||||
var WebSQLTestProvider = require('./websql.js');
|
||||
var MemoryTestProvider = require('./memory.js');
|
||||
var Url = require('url');
|
||||
|
||||
|
@ -16,13 +15,8 @@ function uniqueName() {
|
|||
|
||||
function findBestProvider() {
|
||||
var providers = Filer.FileSystem.providers;
|
||||
if(providers.IndexedDB.isSupported()) {
|
||||
return IndexedDBTestProvider;
|
||||
}
|
||||
if(providers.WebSQL.isSupported()) {
|
||||
return WebSQLTestProvider;
|
||||
}
|
||||
return MemoryTestProvider;
|
||||
return providers.IndexedDB.isSupported() ?
|
||||
IndexedDBTestProvider : MemoryTestProvider;
|
||||
}
|
||||
|
||||
function getUrlParams() {
|
||||
|
@ -49,6 +43,24 @@ function getProviderType() {
|
|||
return queryString['filer-provider'] || defaultProvider;
|
||||
}
|
||||
|
||||
// Run fn() in an environment with indexedDB available
|
||||
// either as-is, or shimmed, removing when done.
|
||||
function shimIndexedDB(fn) {
|
||||
var addShim = !Filer.FileSystem.providers.IndexedDB.isSupported();
|
||||
|
||||
if(addShim) {
|
||||
global.indexedDB = require('fake-indexeddb');
|
||||
}
|
||||
|
||||
var result = fn();
|
||||
|
||||
if(addShim) {
|
||||
delete global.indexedDB;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function setup(callback) {
|
||||
// In browser we support specifying the provider via the query string
|
||||
// (e.g., ?filer-provider=IndexedDB). If not specified, we use
|
||||
|
@ -61,9 +73,6 @@ function setup(callback) {
|
|||
case 'indexeddb':
|
||||
_provider = new IndexedDBTestProvider(name);
|
||||
break;
|
||||
case 'websql':
|
||||
_provider = new WebSQLTestProvider(name);
|
||||
break;
|
||||
case 'memory':
|
||||
_provider = new MemoryTestProvider(name);
|
||||
break;
|
||||
|
@ -150,6 +159,24 @@ const parseBJSON = json =>
|
|||
value
|
||||
);
|
||||
|
||||
function createMockFn(implementation = undefined) {
|
||||
const calls = [];
|
||||
const mockFn = function(...args) {
|
||||
calls.push({
|
||||
args,
|
||||
});
|
||||
if (typeof implementation === 'function') {
|
||||
return implementation(...args);
|
||||
}
|
||||
};
|
||||
Object.defineProperty(mockFn, 'calls', {
|
||||
get() {
|
||||
return calls;
|
||||
}
|
||||
});
|
||||
return mockFn;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
uniqueName: uniqueName,
|
||||
setup: setup,
|
||||
|
@ -158,10 +185,11 @@ module.exports = {
|
|||
provider: provider,
|
||||
providers: {
|
||||
IndexedDB: IndexedDBTestProvider,
|
||||
WebSQL: WebSQLTestProvider,
|
||||
Memory: MemoryTestProvider
|
||||
},
|
||||
cleanup: cleanup,
|
||||
typedArrayEqual: typedArrayEqual,
|
||||
parseBJSON
|
||||
parseBJSON,
|
||||
shimIndexedDB,
|
||||
createMockFn
|
||||
};
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
var Filer = require('../../src');
|
||||
|
||||
var needsCleanup = [];
|
||||
if(global.addEventListener) {
|
||||
global.addEventListener('beforeunload', function() {
|
||||
needsCleanup.forEach(function(f) { f(); });
|
||||
});
|
||||
}
|
||||
|
||||
function WebSQLTestProvider(name) {
|
||||
var _done = false;
|
||||
var that = this;
|
||||
|
||||
function cleanup(callback) {
|
||||
callback = callback || function(){};
|
||||
|
||||
if(!that.provider || _done) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
// Provider is there, but db was never touched
|
||||
if(!that.provider.db) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
var context = that.provider.getReadWriteContext();
|
||||
context.clear(function() {
|
||||
that.provider = null;
|
||||
_done = true;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
if(that.provider) {
|
||||
return;
|
||||
}
|
||||
that.provider = new Filer.FileSystem.providers.WebSQL(name);
|
||||
needsCleanup.push(cleanup);
|
||||
}
|
||||
|
||||
this.init = init;
|
||||
this.cleanup = cleanup;
|
||||
}
|
||||
WebSQLTestProvider.isSupported = function() {
|
||||
return Filer.FileSystem.providers.WebSQL.isSupported();
|
||||
};
|
||||
|
||||
module.exports = WebSQLTestProvider;
|
|
@ -1,5 +1,7 @@
|
|||
var Filer = require('../../src');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const Filer = require('../../src');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('Filer.Errors', function() {
|
||||
it('has expected errors', function() {
|
||||
|
@ -135,7 +137,7 @@ describe('Filer.Errors', function() {
|
|||
});
|
||||
|
||||
it('should include all expected properties by default', function() {
|
||||
var err = new Filer.Errors.ENOENT();
|
||||
const err = new Filer.Errors.ENOENT();
|
||||
expect(err.name).to.equal('ENOENT');
|
||||
expect(err.code).to.equal('ENOENT');
|
||||
expect(err.errno).to.equal(34);
|
||||
|
@ -143,7 +145,7 @@ describe('Filer.Errors', function() {
|
|||
});
|
||||
|
||||
it('should include extra properties when provided', function() {
|
||||
var err = new Filer.Errors.ENOENT('This is the message', '/this/is/the/path');
|
||||
const err = new Filer.Errors.ENOENT('This is the message', '/this/is/the/path');
|
||||
expect(err.name).to.equal('ENOENT');
|
||||
expect(err.code).to.equal('ENOENT');
|
||||
expect(err.errno).to.equal(34);
|
||||
|
@ -152,29 +154,29 @@ describe('Filer.Errors', function() {
|
|||
});
|
||||
|
||||
it('should include default message and path info when provided', function() {
|
||||
var err = new Filer.Errors.ENOENT(null, '/this/is/the/path');
|
||||
const err = new Filer.Errors.ENOENT(null, '/this/is/the/path');
|
||||
expect(err.message).to.equal('no such file or directory');
|
||||
expect(err.path).to.equal('/this/is/the/path');
|
||||
});
|
||||
|
||||
it('should include just the message when no path provided', function() {
|
||||
var err = new Filer.Errors.ENOENT();
|
||||
const err = new Filer.Errors.ENOENT();
|
||||
expect(err.message).to.equal('no such file or directory');
|
||||
expect(err.path).not.to.exist;
|
||||
});
|
||||
|
||||
it('should not include path in toString() when not provided', function() {
|
||||
var err = new Filer.Errors.ENOENT('This is the message');
|
||||
const err = new Filer.Errors.ENOENT('This is the message');
|
||||
expect(err.toString()).to.equal('ENOENT: This is the message');
|
||||
});
|
||||
|
||||
it('should include path in toString() when provided', function() {
|
||||
var err = new Filer.Errors.ENOENT(null, '/this/is/the/path');
|
||||
const err = new Filer.Errors.ENOENT(null, '/this/is/the/path');
|
||||
expect(err.toString()).to.equal('ENOENT: no such file or directory, \'/this/is/the/path\'');
|
||||
});
|
||||
|
||||
it('should include message and path info when provided', function() {
|
||||
var err = new Filer.Errors.ENOENT('This is the message', '/this/is/the/path');
|
||||
const err = new Filer.Errors.ENOENT('This is the message', '/this/is/the/path');
|
||||
expect(err.message).to.equal('This is the message');
|
||||
expect(err.path).to.equal('/this/is/the/path');
|
||||
});
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
var Filer = require('../../src');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const Filer = require('../../src');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('Filer.Buffer', function() {
|
||||
|
||||
|
@ -12,37 +14,37 @@ describe('Filer.Buffer', function() {
|
|||
});
|
||||
|
||||
it('should support .isBuffer()', function() {
|
||||
var buf = Buffer.alloc(0);
|
||||
const buf = Buffer.alloc(0);
|
||||
expect(Buffer.isBuffer(buf)).to.be.true;
|
||||
});
|
||||
|
||||
describe('Deprecation checks - constructor vs. class method init', function() {
|
||||
|
||||
it('should allow new Buffer(array)', function() {
|
||||
var arr = [1, 2, 3];
|
||||
var buf1 = new Buffer(arr);
|
||||
var buf2 = new Buffer.from(arr);
|
||||
const arr = [1, 2, 3];
|
||||
const buf1 = new Buffer(arr);
|
||||
const buf2 = new Buffer.from(arr);
|
||||
expect(buf1).to.deep.equal(buf2);
|
||||
});
|
||||
|
||||
it('should allow new Buffer(ArrayBuffer)', function() {
|
||||
var arrayBuffer = (new Uint8Array([1, 2, 3])).buffer;
|
||||
var buf1 = new Buffer(arrayBuffer);
|
||||
var buf2 = Buffer.from(arrayBuffer);
|
||||
const arrayBuffer = (new Uint8Array([1, 2, 3])).buffer;
|
||||
const buf1 = new Buffer(arrayBuffer);
|
||||
const buf2 = Buffer.from(arrayBuffer);
|
||||
expect(buf1).to.deep.equal(buf2);
|
||||
});
|
||||
|
||||
it('should allow new Buffer(ArrayBuffer)', function() {
|
||||
var buffer = new Buffer.from([1, 2, 3]);
|
||||
var buf1 = new Buffer(buffer);
|
||||
var buf2 = Buffer.from(buffer);
|
||||
const buffer = new Buffer.from([1, 2, 3]);
|
||||
const buf1 = new Buffer(buffer);
|
||||
const buf2 = Buffer.from(buffer);
|
||||
expect(buf1).to.deep.equal(buf2);
|
||||
});
|
||||
|
||||
it('should allow new Buffer(string)', function() {
|
||||
var s = 'Hello World';
|
||||
var buf1 = new Buffer(s);
|
||||
var buf2 = Buffer.from(s);
|
||||
const s = 'Hello World';
|
||||
const buf1 = new Buffer(s);
|
||||
const buf2 = Buffer.from(s);
|
||||
expect(buf1).to.deep.equal(buf2);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
var Filer = require('../../src');
|
||||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
const Filer = require('../../src');
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('Filer.FileSystem', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should properly mount new or existing filesystem', function(done) {
|
||||
var provider = util.provider().provider;
|
||||
const provider = util.provider().provider;
|
||||
|
||||
// 1) Should be able to open a new filesystem, and get empty root
|
||||
var fs1 = new Filer.FileSystem({provider: provider}, function() {
|
||||
const fs1 = new Filer.FileSystem({provider: provider}, function() {
|
||||
fs1.readdir('/', function(err, entries) {
|
||||
expect(err).not.to.exist;
|
||||
expect(entries).to.be.an('array');
|
||||
|
@ -20,7 +21,7 @@ describe('Filer.FileSystem', function() {
|
|||
if(err) throw err;
|
||||
|
||||
// 2) Should be able to open an existing filesystem
|
||||
var fs2 = new Filer.FileSystem({provider: provider}, function() {
|
||||
const fs2 = new Filer.FileSystem({provider: provider}, function() {
|
||||
fs2.readdir('/', function(err, entries) {
|
||||
expect(err).not.to.exist;
|
||||
expect(entries).to.be.an('array');
|
||||
|
@ -29,7 +30,7 @@ describe('Filer.FileSystem', function() {
|
|||
|
||||
|
||||
// 3) FORMAT flag should wipe an existing filesystem
|
||||
var fs3 = new Filer.FileSystem({provider: provider, flags: ['FORMAT']}, function() {
|
||||
const fs3 = new Filer.FileSystem({provider: provider, flags: ['FORMAT']}, function() {
|
||||
fs3.readdir('/', function(err, entries) {
|
||||
expect(err).not.to.exist;
|
||||
expect(entries).to.be.an('array');
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
var Filer = require('../../src');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
const Filer = require('../../src');
|
||||
const util = require('../lib/test-utils');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('Filer', function() {
|
||||
it('is defined', function() {
|
||||
|
@ -10,28 +12,55 @@ describe('Filer', function() {
|
|||
expect(typeof Filer.FileSystem).to.equal('function');
|
||||
});
|
||||
|
||||
it('has Buffer constructor', function() {
|
||||
expect(typeof Filer.Buffer).to.equal('function');
|
||||
});
|
||||
|
||||
it('has Path and path objects', function() {
|
||||
expect(typeof Filer.Path).to.equal('object');
|
||||
expect(typeof Filer.path).to.equal('object');
|
||||
expect(Filer.Path).to.equal(Filer.path);
|
||||
});
|
||||
|
||||
it('has Errors object', function() {
|
||||
expect(typeof Filer.Errors).to.equal('object');
|
||||
});
|
||||
|
||||
it('has an fs object that returns a Filer.FileSystem', function() {
|
||||
// Depends on IndexedDB being available, since we can't
|
||||
// configure our own test provider. Shim for coverage.
|
||||
util.shimIndexedDB(function() {
|
||||
expect(typeof Filer.fs).to.equal('object');
|
||||
|
||||
const fs1 = Filer.fs;
|
||||
const fs2 = Filer.fs;
|
||||
|
||||
expect(fs1).to.be.an.instanceof(Filer.FileSystem);
|
||||
expect(fs2).to.be.an.instanceof(Filer.FileSystem);
|
||||
expect(fs1).to.equal(fs2);
|
||||
});
|
||||
});
|
||||
|
||||
it('has Shell constructor', function() {
|
||||
expect(typeof Filer.Shell).to.equal('function');
|
||||
});
|
||||
|
||||
it('must honor the \'FORMAT\' flag', function(done) {
|
||||
var name = 'local-test';
|
||||
const name = 'local-test';
|
||||
// Because we need to use a bunch of Filer filesystems
|
||||
// in this test, we can't use the usual test infrastructure
|
||||
// to create/manage the fs instance. Pick the best one
|
||||
// based on the testing environment (browser vs. node)
|
||||
var providers = Filer.FileSystem.providers;
|
||||
var Provider;
|
||||
const providers = Filer.FileSystem.providers;
|
||||
let Provider;
|
||||
if(providers.IndexedDB.isSupported()) {
|
||||
Provider = providers.IndexedDB;
|
||||
} else if(providers.WebSQL.isSupported()) {
|
||||
Provider = providers.WebSQL;
|
||||
} else {
|
||||
Provider = providers.Memory;
|
||||
}
|
||||
|
||||
var fs = new Filer.FileSystem({name, provider: new Provider(name)});
|
||||
var fs2 = new Filer.FileSystem({name, provider: new Provider(name)});
|
||||
let fs = new Filer.FileSystem({name, provider: new Provider(name)});
|
||||
let fs2 = new Filer.FileSystem({name, provider: new Provider(name)});
|
||||
|
||||
fs.mkdir('/test', function(err){
|
||||
if(err) throw err;
|
||||
|
|
|
@ -1,17 +1,39 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.access', function () {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should expose access mode flags on fs and fs.constants', function() {
|
||||
const fs = util.fs();
|
||||
|
||||
// F_OK
|
||||
expect(fs.F_OK).to.equal(0);
|
||||
expect(fs.constants.F_OK).to.equal(0);
|
||||
|
||||
// R_OK
|
||||
expect(fs.R_OK).to.equal(4);
|
||||
expect(fs.constants.R_OK).to.equal(4);
|
||||
|
||||
// W_OK
|
||||
expect(fs.W_OK).to.equal(2);
|
||||
expect(fs.constants.W_OK).to.equal(2);
|
||||
|
||||
// X_OK
|
||||
expect(fs.X_OK).to.equal(1);
|
||||
expect(fs.constants.X_OK).to.equal(1);
|
||||
});
|
||||
|
||||
it('should be a function', function () {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(typeof fs.access).to.equal('function');
|
||||
});
|
||||
|
||||
it('should return an error if file does not exist', function (done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.access('/tmp', fs.constants.F_OK, function (error) {
|
||||
expect(error).to.exist;
|
||||
|
@ -21,8 +43,8 @@ describe('fs.access', function () {
|
|||
});
|
||||
|
||||
it('should return no error if file does exist and mode = F_OK', function (done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
fs.writeFile('/myfile', contents, function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -35,8 +57,8 @@ describe('fs.access', function () {
|
|||
});
|
||||
|
||||
it('should return no error if file does exist and mode = R_OK', function (done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
fs.writeFile('/myfile', contents, function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -49,8 +71,8 @@ describe('fs.access', function () {
|
|||
});
|
||||
|
||||
it('should return no error if file does exist and mode = W_OK', function (done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
fs.writeFile('/myfile', contents, function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -62,15 +84,14 @@ describe('fs.access', function () {
|
|||
});
|
||||
});
|
||||
|
||||
// See bug https://github.com/filerjs/filer/issues/602
|
||||
it.skip('should return an error if file is not executable and mode = X_OK', function (done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
it('should return an error if file is not executable and mode = X_OK', function (done) {
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
fs.writeFile('/myfile', contents, function (error) {
|
||||
if (error) throw error;
|
||||
|
||||
fs.chmod('/myfile', 0o644, function(error){
|
||||
fs.chmod('/myfile', '644', function(error){
|
||||
if (error) throw error;
|
||||
|
||||
fs.access('/myfile', fs.constants.X_OK, function (error) {
|
||||
|
@ -83,13 +104,13 @@ describe('fs.access', function () {
|
|||
});
|
||||
|
||||
it('should return no error if file does exist and mode = X_OK', function (done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
fs.writeFile('/myfile', contents, function (error) {
|
||||
if (error) throw error;
|
||||
|
||||
fs.chmod('/myfile', 0o777, function(error){
|
||||
fs.chmod('/myfile', 0o777, function(error) {
|
||||
if (error) throw error;
|
||||
|
||||
fs.access('/myfile', fs.constants.X_OK, function (error) {
|
||||
|
@ -101,8 +122,8 @@ describe('fs.access', function () {
|
|||
});
|
||||
|
||||
it('should return no error if file does exist and no mode is passed', function (done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
fs.writeFile('/myfile', contents, function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -115,8 +136,8 @@ describe('fs.access', function () {
|
|||
});
|
||||
|
||||
it('should return no error if file does exist and mode = R_OK | W_OK', function (done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
fs.writeFile('/myfile', contents, function (error) {
|
||||
if (error) throw error;
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.appendFile', function() {
|
||||
const contents = 'This is a file.';
|
||||
|
||||
beforeEach(function(done) {
|
||||
util.setup(function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
fs.writeFile('/myfile', contents, function(error) {
|
||||
if(error) throw error;
|
||||
done();
|
||||
|
@ -16,13 +18,13 @@ describe('fs.appendFile', function() {
|
|||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.appendFile).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should append a utf8 file without specifying utf8 in appendFile', function(done) {
|
||||
var fs = util.fs();
|
||||
var more = ' Appended.';
|
||||
const fs = util.fs();
|
||||
const more = ' Appended.';
|
||||
|
||||
fs.appendFile('/myfile', more, function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -36,8 +38,8 @@ describe('fs.appendFile', function() {
|
|||
});
|
||||
|
||||
it('should append a utf8 file with "utf8" option to appendFile', function(done) {
|
||||
var fs = util.fs();
|
||||
var more = ' Appended.';
|
||||
const fs = util.fs();
|
||||
const more = ' Appended.';
|
||||
|
||||
fs.appendFile('/myfile', more, 'utf8', function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -51,8 +53,8 @@ describe('fs.appendFile', function() {
|
|||
});
|
||||
|
||||
it('should append a utf8 file with {encoding: "utf8"} option to appendFile', function(done) {
|
||||
var fs = util.fs();
|
||||
var more = ' Appended.';
|
||||
const fs = util.fs();
|
||||
const more = ' Appended.';
|
||||
|
||||
fs.appendFile('/myfile', more, { encoding: 'utf8' }, function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -66,12 +68,12 @@ describe('fs.appendFile', function() {
|
|||
});
|
||||
|
||||
it('should append a binary file', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
// String and utf8 binary encoded versions of the same thing: 'This is a file.'
|
||||
var binary = Buffer.from([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
|
||||
var binary2 = Buffer.from([32, 65, 112, 112, 101, 110, 100, 101, 100, 46]);
|
||||
var binary3 = Buffer.from([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46,
|
||||
const binary = Buffer.from([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
|
||||
const binary2 = Buffer.from([32, 65, 112, 112, 101, 110, 100, 101, 100, 46]);
|
||||
const binary3 = Buffer.from([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46,
|
||||
32, 65, 112, 112, 101, 110, 100, 101, 100, 46]);
|
||||
|
||||
fs.writeFile('/mybinaryfile', binary, function(error) {
|
||||
|
@ -90,9 +92,9 @@ describe('fs.appendFile', function() {
|
|||
});
|
||||
|
||||
it('should follow symbolic links', function(done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
var more = ' Appended.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
const more = ' Appended.';
|
||||
|
||||
fs.symlink('/myfile', '/myFileLink', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -110,7 +112,7 @@ describe('fs.appendFile', function() {
|
|||
});
|
||||
|
||||
it('should work when file does not exist, and create the file', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.appendFile('/newfile', contents, { encoding: 'utf8' }, function(error) {
|
||||
expect(error).not.to.exist;
|
||||
|
@ -124,8 +126,8 @@ describe('fs.appendFile', function() {
|
|||
});
|
||||
|
||||
it('should accept numbers and append them to the file', function(done) {
|
||||
var fs = util.fs();
|
||||
var more = 10000;
|
||||
const fs = util.fs();
|
||||
const more = 10000;
|
||||
|
||||
fs.appendFile('/myfile', more, 'utf8', function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -142,7 +144,7 @@ describe('fs.appendFile', function() {
|
|||
describe('fs.promises.appendFile', function() {
|
||||
beforeEach(function(done) {
|
||||
util.setup(function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
return fs.promises.writeFile('/myfile', 'This is a file.', { encoding: 'utf8' })
|
||||
.then(done)
|
||||
.catch(done);
|
||||
|
@ -151,14 +153,14 @@ describe('fs.promises.appendFile', function() {
|
|||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.promises.appendFile).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should append a utf8 file without specifying utf8 in appendFile', function() {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
var more = ' Appended.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
const more = ' Appended.';
|
||||
|
||||
return fs.promises.appendFile('/myfile', more)
|
||||
.then(() => fs.promises.readFile('/myfile', 'utf8'))
|
||||
|
@ -166,9 +168,9 @@ describe('fs.promises.appendFile', function() {
|
|||
});
|
||||
|
||||
it('should append a utf8 file with "utf8" option to appendFile', function() {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
var more = ' Appended.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
const more = ' Appended.';
|
||||
|
||||
return fs.promises.appendFile('/myfile', more, 'utf8')
|
||||
.then(() => fs.promises.readFile('/myfile', 'utf8'))
|
||||
|
@ -176,9 +178,9 @@ describe('fs.promises.appendFile', function() {
|
|||
});
|
||||
|
||||
it('should append a utf8 file with {encoding: "utf8"} option to appendFile', function() {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
var more = ' Appended.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
const more = ' Appended.';
|
||||
|
||||
return fs.promises.appendFile('/myfile', more, { encoding: 'utf8' })
|
||||
.then(() => fs.promises.readFile('/myfile', { encoding: 'utf8' }))
|
||||
|
@ -186,12 +188,12 @@ describe('fs.promises.appendFile', function() {
|
|||
});
|
||||
|
||||
it('should append a binary file', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
// String and utf8 binary encoded versions of the same thing: 'This is a file.'
|
||||
var binary = new Buffer([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
|
||||
var binary2 = new Buffer([32, 65, 112, 112, 101, 110, 100, 101, 100, 46]);
|
||||
var binary3 = new Buffer([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46,
|
||||
const binary = new Buffer([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
|
||||
const binary2 = new Buffer([32, 65, 112, 112, 101, 110, 100, 101, 100, 46]);
|
||||
const binary3 = new Buffer([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46,
|
||||
32, 65, 112, 112, 101, 110, 100, 101, 100, 46]);
|
||||
|
||||
return fs.promises.writeFile('/mybinaryfile', binary)
|
||||
|
@ -201,9 +203,9 @@ describe('fs.promises.appendFile', function() {
|
|||
});
|
||||
|
||||
it('should follow symbolic links', function() {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
var more = ' Appended.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
const more = ' Appended.';
|
||||
|
||||
return fs.promises.symlink('/myfile', '/myFileLink')
|
||||
.then(() => fs.promises.appendFile('/myFileLink', more, 'utf8'))
|
||||
|
@ -212,8 +214,8 @@ describe('fs.promises.appendFile', function() {
|
|||
});
|
||||
|
||||
it('should work when file does not exist, and create the file', function() {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
return fs.promises.appendFile('/newfile', contents, { encoding: 'utf8' })
|
||||
.then(() => fs.promises.readFile('/newfile', 'utf8'))
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.chmod, fs.fchmod', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be functions', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(typeof fs.chmod).to.equal('function');
|
||||
expect(typeof fs.fchmod).to.equal('function');
|
||||
});
|
||||
|
||||
it('should automatically set mode=755 for a directory', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/dir', function(err) {
|
||||
if(err) throw err;
|
||||
|
@ -26,7 +28,7 @@ describe('fs.chmod, fs.fchmod', function() {
|
|||
});
|
||||
|
||||
it('should automatically set mode=644 for a file', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/file', 'w', function(err, fd) {
|
||||
if(err) throw err;
|
||||
|
@ -40,7 +42,7 @@ describe('fs.chmod, fs.fchmod', function() {
|
|||
});
|
||||
|
||||
it('should be an error when the path is invalid', function(done){
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
fs.chmod('/invalid_path', 0o444, function(err){
|
||||
expect(err).to.exist;
|
||||
expect(err.code).to.equal('ENOENT');
|
||||
|
@ -49,7 +51,7 @@ describe('fs.chmod, fs.fchmod', function() {
|
|||
});
|
||||
|
||||
it('should error if mode value is a non-numeric string', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/dir', function(err) {
|
||||
if(err) throw err;
|
||||
|
@ -63,7 +65,7 @@ describe('fs.chmod, fs.fchmod', function() {
|
|||
});
|
||||
|
||||
it('should error if mode value is null', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/dir', function(err) {
|
||||
if(err) throw err;
|
||||
|
@ -77,7 +79,7 @@ describe('fs.chmod, fs.fchmod', function() {
|
|||
});
|
||||
|
||||
it('should error if mode value is non-integer number', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/dir', function(err) {
|
||||
if(err) throw err;
|
||||
|
@ -91,7 +93,7 @@ describe('fs.chmod, fs.fchmod', function() {
|
|||
});
|
||||
|
||||
it('should error if mode value is non-integer number', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/dir', function(err) {
|
||||
if(err) throw err;
|
||||
|
@ -105,7 +107,7 @@ describe('fs.chmod, fs.fchmod', function() {
|
|||
});
|
||||
|
||||
it('should allow octal strings for mode value', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/dir', function(err) {
|
||||
if(err) throw err;
|
||||
|
@ -124,7 +126,7 @@ describe('fs.chmod, fs.fchmod', function() {
|
|||
});
|
||||
|
||||
it('should allow for updating mode of a given file', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/file', 'w', function(err, fd) {
|
||||
if(err) throw err;
|
||||
|
@ -161,12 +163,12 @@ describe('fsPromise.chmod', function() {
|
|||
afterEach(util.setup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fsPromise = util.fs().promises;
|
||||
const fsPromise = util.fs().promises;
|
||||
expect(typeof fsPromise.chmod).to.equal('function');
|
||||
});
|
||||
|
||||
it('should allow for updating mode of a given file', function() {
|
||||
var fsPromise = util.fs().promises;
|
||||
const fsPromise = util.fs().promises;
|
||||
|
||||
return fsPromise.open('/file', 'w')
|
||||
.then(() => fsPromise.chmod('/file', 0o444))
|
||||
|
|
|
@ -36,7 +36,7 @@ describe('fs.chown, fs.fchown', function() {
|
|||
fs.fchown(fd, '1001', 1001, function(err) {
|
||||
expect(err).to.exist;
|
||||
expect(err.code).to.equal('EINVAL');
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -64,7 +64,7 @@ describe('fs.chown, fs.fchown', function() {
|
|||
fs.fchown(fd, 1001, '1001', function(err) {
|
||||
expect(err).to.exist;
|
||||
expect(err.code).to.equal('EINVAL');
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,28 +1,31 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.close', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(typeof fs.close).to.equal('function');
|
||||
});
|
||||
|
||||
it('should release the file descriptor', function(done) {
|
||||
var buffer = Buffer.alloc(0);
|
||||
var fs = util.fs();
|
||||
const buffer = Buffer.alloc(0);
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, result) {
|
||||
if(error) throw error;
|
||||
|
||||
var fd = result;
|
||||
const fd = result;
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.read(fd, buffer, 0, buffer.length, undefined, function(error, result) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('EBADF');
|
||||
expect(result).not.to.exist;
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.exists', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(typeof fs.exists).to.equal('function');
|
||||
});
|
||||
|
||||
it('should return false if path does not exist', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.exists('/tmp', function(result) {
|
||||
expect(result).to.be.false;
|
||||
|
@ -20,7 +21,7 @@ describe('fs.exists', function() {
|
|||
});
|
||||
|
||||
it('should return true if path exists', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w', function(err, fd) {
|
||||
if(err) throw err;
|
||||
|
@ -37,7 +38,7 @@ describe('fs.exists', function() {
|
|||
});
|
||||
|
||||
it('should follow symbolic links and return true for the resulting path', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
@ -58,7 +59,7 @@ describe('fs.exists', function() {
|
|||
});
|
||||
|
||||
it('should follow symbolic links and return false if for the resulting path does not exist', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
|
|
@ -77,7 +77,7 @@ describe('fs.lseek', function() {
|
|||
expect(result.size).to.equal(offset + buffer.length);
|
||||
var expected = Buffer.from([1, 2, 3, 1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
expect(result_buffer).to.deep.equal(expected);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -117,7 +117,7 @@ describe('fs.lseek', function() {
|
|||
expect(result.size).to.equal(offset + 2 * buffer.length);
|
||||
var expected = Buffer.from([1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
expect(result_buffer).to.deep.equal(expected);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -163,7 +163,12 @@ describe('fs.lseek', function() {
|
|||
|
||||
var expected = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
expect(result_buffer).to.deep.equal(expected);
|
||||
done();
|
||||
|
||||
fs.close(fd1, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.close(fd2, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.lstat', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(typeof fs.lstat).to.equal('function');
|
||||
});
|
||||
|
||||
it('should return an error if path does not exist', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
const fs = util.fs();
|
||||
|
||||
fs.lstat('/tmp', function(error, result) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('ENOENT');
|
||||
|
@ -22,8 +23,8 @@ describe('fs.lstat', function() {
|
|||
});
|
||||
|
||||
it('should return a stat object if path is not a symbolic link', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
const fs = util.fs();
|
||||
|
||||
fs.lstat('/', function(error, result) {
|
||||
expect(error).not.to.exist;
|
||||
expect(result).to.exist;
|
||||
|
@ -33,8 +34,8 @@ describe('fs.lstat', function() {
|
|||
});
|
||||
|
||||
it('should return a stat object if path is a symbolic link', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
const fs = util.fs();
|
||||
|
||||
fs.symlink('/', '/mylink', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
|
@ -46,6 +47,27 @@ describe('fs.lstat', function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should have a mode (full node) when stat\'d with lstat', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.writeFile('/file', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.symlink('/file', '/symlink', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.lstat('/symlink', function(error, stats) {
|
||||
if(error) throw error;
|
||||
|
||||
// We should build and return a full node object, complete with
|
||||
// calculated mode, which should be a SYMLINK and the default file permissions.
|
||||
expect(stats.mode).to.equal(fs.constants.S_IFLNK | 0o644);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('fs.promises.lstat', () => {
|
||||
|
@ -53,7 +75,7 @@ describe('fs.promises.lstat', () => {
|
|||
afterEach(util.cleanup);
|
||||
|
||||
it('should return an error if path does not exist', () => {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.lstat('/tmp')
|
||||
.catch( error => {
|
||||
|
@ -63,8 +85,8 @@ describe('fs.promises.lstat', () => {
|
|||
});
|
||||
|
||||
it('should return a stat object if path is not a symbolic link', () => {
|
||||
var fsPromises = util.fs().promises;
|
||||
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.lstat('/')
|
||||
.then(result => {
|
||||
expect(result).to.exist;
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.mkdir', function () {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function () {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.mkdir).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should return an error if part of the parent path does not exist', function (done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/tmp/mydir', function (error) {
|
||||
expect(error).to.exist;
|
||||
|
@ -21,7 +22,7 @@ describe('fs.mkdir', function () {
|
|||
});
|
||||
|
||||
it('should return an error if the path already exists', function (done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/', function (error) {
|
||||
expect(error).to.exist;
|
||||
|
@ -31,7 +32,7 @@ describe('fs.mkdir', function () {
|
|||
});
|
||||
|
||||
it('should make a new directory', function (done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/tmp', function (error) {
|
||||
expect(error).not.to.exist;
|
||||
|
@ -52,12 +53,12 @@ describe('fs.promises.mkdir', function () {
|
|||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function () {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.promises.mkdir).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should return an error if part of the parent path does not exist', function () {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
return fs.promises.mkdir('/tmp/mydir')
|
||||
.catch(error => {
|
||||
|
@ -67,7 +68,7 @@ describe('fs.promises.mkdir', function () {
|
|||
});
|
||||
|
||||
it('should return an error if the path already exists', function () {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
return fs.promises.mkdir('/')
|
||||
.catch(error =>{
|
||||
|
@ -77,7 +78,7 @@ describe('fs.promises.mkdir', function () {
|
|||
});
|
||||
|
||||
it('should make a new directory', function () {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
return fs.promises.mkdir('/tmp')
|
||||
.then(() => fs.promises.stat('/tmp'))
|
||||
|
@ -88,7 +89,7 @@ describe('fs.promises.mkdir', function () {
|
|||
});
|
||||
|
||||
it('should return a promise', function () {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.promises.mkdir('/tmp')).to.be.a('promise');
|
||||
});
|
||||
});
|
|
@ -1,17 +1,19 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.mkdtemp', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.mkdtemp).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should craete temp dir with specified prefix', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
fs.mkdtemp('/foo', function(error, path) {
|
||||
expect(error).not.to.exist;
|
||||
expect(path).to.match(/foo-\w{6}/);
|
||||
|
@ -20,7 +22,7 @@ describe('fs.mkdtemp', function() {
|
|||
});
|
||||
|
||||
it('should craete temp dir inside existing directory', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
fs.mkdir('/myDir', (error) => {
|
||||
expect(error).not.to.exist;
|
||||
fs.mkdtemp('/myDir/foo', function(error, path) {
|
||||
|
@ -32,7 +34,7 @@ describe('fs.mkdtemp', function() {
|
|||
});
|
||||
|
||||
it('should not create temp dir without prefix', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
fs.mkdtemp('', function(error, path) {
|
||||
expect(error).to.exist;
|
||||
expect(path).not.to.exist;
|
||||
|
@ -41,7 +43,7 @@ describe('fs.mkdtemp', function() {
|
|||
});
|
||||
|
||||
it('should not create temp dir inside non existing dir', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
fs.mkdtemp('/doesNotExists/foo', function(error, path) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.be.equal('ENOENT');
|
||||
|
@ -49,4 +51,4 @@ describe('fs.mkdtemp', function() {
|
|||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
var constants = require('../../src/constants.js');
|
||||
var { FIRST_DESCRIPTOR } = require('../../src/constants.js');
|
||||
|
||||
describe('fs.open', function() {
|
||||
beforeEach(util.setup);
|
||||
|
@ -47,6 +47,23 @@ describe('fs.open', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should return an error when flagged for write and the path exists', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.mkdir('/tmp', function(error) {
|
||||
if(error) throw error;
|
||||
fs.writeFile('/tmp/file', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
fs.open('/tmp/file', 'wx', function(error, result) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('EEXIST');
|
||||
expect(result).not.to.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an error when flagged for append and the path is a directory', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
|
@ -63,45 +80,68 @@ describe('fs.open', function() {
|
|||
|
||||
it('should return a unique file descriptor', function(done) {
|
||||
var fs = util.fs();
|
||||
var fd1;
|
||||
|
||||
fs.open('/file1', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
expect(error).not.to.exist;
|
||||
expect(fd).to.be.a('number');
|
||||
|
||||
fs.open('/file2', 'w+', function(error, fd) {
|
||||
fs.open('/file2', 'w+', function(error, fd1) {
|
||||
if(error) throw error;
|
||||
expect(error).not.to.exist;
|
||||
expect(fd).to.be.a('number');
|
||||
expect(fd).not.to.equal(fd1);
|
||||
done();
|
||||
expect(fd1).to.be.a('number');
|
||||
expect(fd1).not.to.equal(fd);
|
||||
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.close(fd1, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the argument value of the file descriptor index matching the value set by the first useable file descriptor constant', function(done) {
|
||||
it('should return the argument value of the file descriptor index greater than or equal to the value set by the first useable file descriptor constant', function(done) {
|
||||
var fs = util.fs();
|
||||
var firstFD = constants.FIRST_DESCRIPTOR;
|
||||
|
||||
fs.open('/file1', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
expect(fd).to.equal(firstFD);
|
||||
done();
|
||||
expect(fd).to.equal(FIRST_DESCRIPTOR);
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should reuse file descriptors after closing', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/file1', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
expect(fd).to.equal(FIRST_DESCRIPTOR);
|
||||
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.open('/file1', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
expect(fd).to.equal(FIRST_DESCRIPTOR);
|
||||
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a new file when flagged for write', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w', function(error) {
|
||||
fs.open('/myfile', 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.stat('/myfile', function(error, result) {
|
||||
expect(error).not.to.exist;
|
||||
expect(result).to.exist;
|
||||
expect(result.isFile()).to.be.true;
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -110,7 +150,7 @@ describe('fs.open', function() {
|
|||
it('should create a new file, when flagged for write, and set the mode to the passed value', function(done) {
|
||||
|
||||
var fs = util.fs();
|
||||
fs.open('/myfile', 'w', 0o777, function(error) {
|
||||
fs.open('/myfile', 'w', 0o777, function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.stat('/myfile', function(error, result) {
|
||||
|
@ -118,7 +158,7 @@ describe('fs.open', function() {
|
|||
expect(result).to.exist;
|
||||
expect(result.mode).to.exist;
|
||||
expect(result.mode & 0o777).to.equal(0o777);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -126,7 +166,7 @@ describe('fs.open', function() {
|
|||
it('should create a new file, but no mode is passed, so the default value of 644 should be seen', function(done) {
|
||||
|
||||
var fs = util.fs();
|
||||
fs.open('/myfile', 'w', function(error) {
|
||||
fs.open('/myfile', 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.stat('/myfile', function(error, result) {
|
||||
|
@ -134,7 +174,7 @@ describe('fs.open', function() {
|
|||
expect(result).to.exist;
|
||||
expect(result.mode).to.exist;
|
||||
expect(result.mode & 0o644).to.equal(0o644);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -162,8 +202,7 @@ describe('fs.open', function() {
|
|||
expect(error.code).to.equal('EBADF');
|
||||
expect(result).not.to.exist;
|
||||
|
||||
fs.close(fd);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -180,22 +219,3 @@ describe('fs.open', function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* fsPromise.open() Tests
|
||||
**/
|
||||
describe('fsPromises.open', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should return an error if the parent path does not exist', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.open('/tmp/myfile', 'w+')
|
||||
.then(result => expect(result).not.to.exist)
|
||||
.catch(error => {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('ENOENT');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.read', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.read).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should read data from a file', function(done) {
|
||||
var fs = util.fs();
|
||||
var wbuffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
var rbuffer = Buffer.alloc(wbuffer.length);
|
||||
const fs = util.fs();
|
||||
const wbuffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
const rbuffer = Buffer.alloc(wbuffer.length);
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.write(fd, wbuffer, 0, wbuffer.length, 0, function(error, result) {
|
||||
if(error) throw error;
|
||||
expect(result).to.equal(wbuffer.length);
|
||||
|
@ -25,17 +27,17 @@ describe('fs.read', function() {
|
|||
expect(error).not.to.exist;
|
||||
expect(result).to.equal(rbuffer.length);
|
||||
expect(wbuffer).to.deep.equal(rbuffer);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update the current file position', function(done) {
|
||||
var fs = util.fs();
|
||||
var wbuffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
var rbuffer = Buffer.alloc(wbuffer.length);
|
||||
var _result = 0;
|
||||
const fs = util.fs();
|
||||
const wbuffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
const rbuffer = Buffer.alloc(wbuffer.length);
|
||||
let _result = 0;
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
@ -54,7 +56,7 @@ describe('fs.read', function() {
|
|||
expect(error).not.to.exist;
|
||||
expect(_result).to.equal(rbuffer.length);
|
||||
expect(wbuffer).to.deep.equal(rbuffer);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -62,9 +64,9 @@ describe('fs.read', function() {
|
|||
});
|
||||
|
||||
it('should fail to read a directory', function(done) {
|
||||
var fs = util.fs();
|
||||
var buf = Buffer.alloc(20);
|
||||
var buf2 = Buffer.alloc(20);
|
||||
const fs = util.fs();
|
||||
const buf = Buffer.alloc(20);
|
||||
const buf2 = Buffer.alloc(20);
|
||||
|
||||
fs.mkdir('/mydir', function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -77,17 +79,17 @@ describe('fs.read', function() {
|
|||
expect(error.code).to.equal('EISDIR');
|
||||
expect(result).to.equal(0);
|
||||
expect(buf).to.deep.equal(buf2);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail to read a file that does not exist', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
var fd = 0;
|
||||
var rbuffer = Buffer.alloc(8);
|
||||
const fd = 0;
|
||||
const rbuffer = Buffer.alloc(8);
|
||||
|
||||
fs.read(fd, rbuffer, 0, rbuffer.length, 0, function(error, result) {
|
||||
expect(error).to.exist;
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.readdir', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.readdir).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should return an error if the path does not exist', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.readdir('/tmp/mydir', function(error, files) {
|
||||
expect(error).to.exist;
|
||||
|
@ -22,7 +24,7 @@ describe('fs.readdir', function() {
|
|||
});
|
||||
|
||||
it('should return a list of files from an existing directory', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/tmp', function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -38,7 +40,7 @@ describe('fs.readdir', function() {
|
|||
});
|
||||
|
||||
it('should follow symbolic links', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/tmp', function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -56,12 +58,12 @@ describe('fs.readdir', function() {
|
|||
});
|
||||
|
||||
it('(promise) should be a function', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
expect(fsPromises.readdir).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should return an error if the path is a file', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.writeFile('/myfile', 'contents')
|
||||
.then(() => fsPromises.readdir('/myfile'))
|
||||
|
@ -72,7 +74,7 @@ describe('fs.readdir', function() {
|
|||
});
|
||||
|
||||
it('(promise) should return a list of files from an existing directory', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.mkdir('/tmp')
|
||||
.then(() => {
|
||||
|
|
|
@ -1,42 +1,59 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
describe('fs.readlink', function() {
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.readlink', function () {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
it('should be a function', function () {
|
||||
const fs = util.fs();
|
||||
expect(fs.readlink).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should return an error if part of the parent destination path does not exist', function(done) {
|
||||
var fs = util.fs();
|
||||
it('should return an error if part of the parent destination path does not exist', function (done) {
|
||||
const fs = util.fs();
|
||||
|
||||
fs.readlink('/tmp/mydir', function(error) {
|
||||
fs.readlink('/tmp/mydir', function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('ENOENT');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an error if the path is not a symbolic link', function(done) {
|
||||
var fs = util.fs();
|
||||
it('should return an error if the path is not a symbolic link', function (done) {
|
||||
const fs = util.fs();
|
||||
|
||||
fs.readlink('/', function(error) {
|
||||
fs.readlink('/', function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('ENOENT');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the contents of a symbolic link', function(done) {
|
||||
var fs = util.fs();
|
||||
it('should return an error if the path is not a symbolic link', function (done) {
|
||||
const fs = util.fs();
|
||||
|
||||
fs.symlink('/', '/myfile', function(error) {
|
||||
if(error) throw error;
|
||||
fs.mkdir('/tmp', function (error) {
|
||||
if (error) throw error;
|
||||
|
||||
fs.readlink('/myfile', function(error, result) {
|
||||
fs.readlink('/tmp', function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the contents of a symbolic link', function (done) {
|
||||
const fs = util.fs();
|
||||
|
||||
fs.symlink('/', '/myfile', function (error) {
|
||||
if (error) throw error;
|
||||
|
||||
fs.readlink('/myfile', function (error, result) {
|
||||
expect(error).not.to.exist;
|
||||
expect(result).to.equal('/');
|
||||
done();
|
||||
|
@ -44,24 +61,24 @@ describe('fs.readlink', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should allow relative paths, but resolve to the dstpath', function(done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'contents';
|
||||
it('should allow relative paths, but resolve to the dstpath', function (done) {
|
||||
const fs = util.fs();
|
||||
const contents = 'contents';
|
||||
|
||||
fs.mkdir('/dir', function(error) {
|
||||
if(error) throw error;
|
||||
fs.mkdir('/dir', function (error) {
|
||||
if (error) throw error;
|
||||
|
||||
fs.writeFile('/file', contents, function(error) {
|
||||
if(error) throw error;
|
||||
fs.writeFile('/file', contents, function (error) {
|
||||
if (error) throw error;
|
||||
|
||||
fs.symlink('../file', '/dir/symlink', function(error) {
|
||||
if(error) throw error;
|
||||
fs.symlink('../file', '/dir/symlink', function (error) {
|
||||
if (error) throw error;
|
||||
|
||||
fs.readlink('/dir/symlink', function(error, result) {
|
||||
fs.readlink('/dir/symlink', function (error, result) {
|
||||
expect(error).not.to.exist;
|
||||
expect(result).to.equal('../file');
|
||||
|
||||
fs.readFile('/dir/symlink', 'utf8', function(error, data) {
|
||||
fs.readFile('/dir/symlink', 'utf8', function (error, data) {
|
||||
expect(error).not.to.exist;
|
||||
expect(data).to.equal(contents);
|
||||
done();
|
||||
|
|
|
@ -20,7 +20,7 @@ describe('fs.rename', function() {
|
|||
if(error) throw error;
|
||||
|
||||
fs.rename('/myfile', '/myfile', function(error) {
|
||||
expect(error).not.to.exist;
|
||||
expect(error).not.to.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -108,6 +108,35 @@ describe('fs.rename', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should rename an existing directory into another sub directory', () => {
|
||||
var fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.mkdir('/mydir')
|
||||
.then(() => fsPromises.mkdir('/mydir/subdir'))
|
||||
.then(() => fsPromises.mkdir('/anotherdir'))
|
||||
.then(() => fsPromises.rename('/mydir', '/anotherdir/originaldir'))
|
||||
.then(() => { fsPromises.stat('/mydir')
|
||||
.catch((error) => {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('ENOENT');
|
||||
});
|
||||
})
|
||||
.then(() => { fsPromises.stat('/anotherdir/mydir')
|
||||
.catch((error) => {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('ENOENT');
|
||||
});
|
||||
})
|
||||
.then(() => { fsPromises.stat('/anotherdir/originaldir/subdir')
|
||||
.then(result => {
|
||||
expect(result.nlinks).to.equal(1);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error) throw error;
|
||||
});
|
||||
});
|
||||
|
||||
it('should rename an existing directory if the new path points to an existing directory', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
var Filer = require('../../src');
|
||||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const Filer = require('../../src');
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.Shell', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('is a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(typeof fs.Shell).to.equal('function');
|
||||
});
|
||||
|
||||
it('should return a FileSystemShell instance', function() {
|
||||
var fs = util.fs();
|
||||
var sh = new fs.Shell();
|
||||
const fs = util.fs();
|
||||
const sh = new fs.Shell();
|
||||
|
||||
expect(sh.prototype).to.deep.equal((new Filer.Shell(fs)).prototype);
|
||||
});
|
||||
|
||||
it('should reflect changes to the prototype', function(){
|
||||
var fs = util.fs();
|
||||
var sh = new fs.Shell();
|
||||
const fs = util.fs();
|
||||
const sh = new fs.Shell();
|
||||
|
||||
Filer.Shell.prototype.test = 'foo';
|
||||
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
var Filer = require('../../src');
|
||||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const Filer = require('../../src');
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('is an object', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(typeof fs).to.equal('object');
|
||||
expect(fs).to.be.an.instanceof(Filer.FileSystem);
|
||||
});
|
||||
|
||||
it('should have a root directory', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
fs.stat('/', function(error, result) {
|
||||
expect(error).not.to.exist;
|
||||
expect(result).to.exist;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
var chai = require('chai');
|
||||
chai.use(require('chai-datetime'));
|
||||
var expect = chai.expect;
|
||||
var Path = require('../../src').Path;
|
||||
|
||||
describe('fs.stat', function() {
|
||||
beforeEach(util.setup);
|
||||
|
@ -55,9 +58,9 @@ describe('fs.stat', function() {
|
|||
expect(result['mtime']).to.be.a('date');
|
||||
expect(result['ctime']).to.be.a('date');
|
||||
|
||||
expect(result.atime.getTime()/1000).to.equal(result.atimeMs);
|
||||
expect(result.mtime.getTime()/1000).to.equal(result.mtimeMs);
|
||||
expect(result.ctime.getTime()/1000).to.equal(result.ctimeMs);
|
||||
expect(result.atime.getTime()).to.equal(result.atimeMs);
|
||||
expect(result.mtime.getTime()).to.equal(result.mtimeMs);
|
||||
expect(result.ctime.getTime()).to.equal(result.ctimeMs);
|
||||
|
||||
done();
|
||||
});
|
||||
|
@ -113,7 +116,7 @@ describe('fs.stat', function() {
|
|||
expect(result['ctimeMs']).to.be.a('number');
|
||||
expect(result['type']).to.equal('FILE');
|
||||
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -152,6 +155,352 @@ describe('fs.stat', function() {
|
|||
expect(result.isDirectory()).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
it('should set appropriate time and timeMs values when creating a file', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
// Make sure that all times on a file node are within a 1 minute window
|
||||
var before = new Date();
|
||||
var oneMinuteLater = new Date();
|
||||
oneMinuteLater.setMinutes(oneMinuteLater.getMinutes() + 1);
|
||||
|
||||
fs.writeFile('/file', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.stat('/file', function(error, stats) {
|
||||
if(error) throw error;
|
||||
|
||||
expect(new Date(stats.ctimeMs)).to.be.withinDate(before, oneMinuteLater);
|
||||
expect(stats.ctime).to.be.withinDate(before, oneMinuteLater);
|
||||
|
||||
expect(new Date(stats.atimeMs)).to.be.withinDate(before, oneMinuteLater);
|
||||
expect(stats.atime).to.be.withinDate(before, oneMinuteLater);
|
||||
|
||||
expect(new Date(stats.mtimeMs)).to.be.withinDate(before, oneMinuteLater);
|
||||
expect(stats.mtime).to.be.withinDate(before, oneMinuteLater);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should set appropriate time and timeMs values when creating a file', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.writeFile('/file', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
var newAtime = new Date('1 Oct 2000 15:33:22');
|
||||
var newMtime = new Date('30 Sep 2000 06:43:54');
|
||||
|
||||
fs.utimes('/file', newAtime, newMtime, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.stat('/file', function(error, stats) {
|
||||
if(error) throw error;
|
||||
|
||||
// ctime should match newMtime
|
||||
expect(stats.ctimeMs).to.equal(newMtime.getTime());
|
||||
expect(stats.ctime).to.equalDate(newMtime);
|
||||
|
||||
// atime should match newAtime
|
||||
expect(stats.atimeMs).to.equal(newAtime.getTime());
|
||||
expect(stats.atime).to.equalDate(newAtime);
|
||||
|
||||
// mtime should match newMtime
|
||||
expect(stats.mtimeMs).to.equal(newMtime.getTime());
|
||||
expect(stats.mtime).to.equalDate(newMtime);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('fs.stats', function() {
|
||||
describe('#isFile()', function() {
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isFile).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return true if stats are for file', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.fstat(fd, function(error, stats) {
|
||||
expect(error).not.to.exist;
|
||||
expect(stats.isFile()).to.be.true;
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for directory', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isFile()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for symbolic link', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.symlink('/myfile', '/myfilelink', function(error) {
|
||||
if(error) throw error;
|
||||
fs.lstat('/myfilelink', function(error, stats) {
|
||||
expect(error).not.to.exist;
|
||||
expect(stats.isFile()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isDirectory()', function() {
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isDirectory).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for file', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
fs.fstat(fd, function(error, stats) {
|
||||
expect(error).not.to.exist;
|
||||
expect(stats.isDirectory()).to.be.false;
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return true if stats are for directory', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isDirectory()).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for symbolic link', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
fs.symlink('/myfile', '/myfilelink', function(error) {
|
||||
if(error) throw error;
|
||||
fs.lstat('/myfilelink', function(error, stats) {
|
||||
expect(stats.isDirectory()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isBlockDevice()', function() {
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isBlockDevice).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isBlockDevice()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isCharacterDevice()', function() {
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isCharacterDevice).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isCharacterDevice()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isSymbolicLink()', function() {
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isSymbolicLink).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for file', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
fs.fstat(fd, function(error, stats) {
|
||||
expect(error).not.to.exist;
|
||||
expect(stats.isSymbolicLink()).to.be.false;
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for directory', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isSymbolicLink()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return true if stats are for symbolic link', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
fs.symlink('/myfile', '/myfilelink', function(error) {
|
||||
if(error) throw error;
|
||||
fs.lstat('/myfilelink', function(error, stats) {
|
||||
expect(stats.isSymbolicLink()).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isFIFO()', function() {
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isFIFO).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isFIFO()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isSocket()', function() {
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isSocket).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isSocket()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('generated name property', function() {
|
||||
|
||||
it('should correct return name for a file', function(done) {
|
||||
var fs = util.fs();
|
||||
var filepath = '/a';
|
||||
|
||||
fs.writeFile(filepath, 'data', function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.stat(filepath, function(err, stats) {
|
||||
if(err) throw err;
|
||||
|
||||
expect(stats.name).to.equal(Path.basename(filepath));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should correct return name for an fd', function(done) {
|
||||
var fs = util.fs();
|
||||
var filepath = '/a';
|
||||
|
||||
fs.open(filepath, 'w', function(err, fd) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.fstat(fd, function(err, stats) {
|
||||
if(err) throw err;
|
||||
|
||||
expect(stats.name).to.equal(Path.basename(filepath));
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,298 +0,0 @@
|
|||
var Path = require('../../src').Path;
|
||||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
|
||||
describe('fs.stats', function() {
|
||||
describe('#isFile()', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isFile).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return true if stats are for file', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
fs.fstat(fd, function(error, stats) {
|
||||
expect(stats.isFile()).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for directory', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isFile()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for symbolic link', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.symlink('/myfile', '/myfilelink', function(error) {
|
||||
if(error) throw error;
|
||||
fs.lstat('/myfilelink', function(error, stats) {
|
||||
expect(stats.isFile()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isDirectory()', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isDirectory).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for file', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
fs.fstat(fd, function(error, stats) {
|
||||
expect(stats.isDirectory()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return true if stats are for directory', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isDirectory()).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for symbolic link', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
fs.symlink('/myfile', '/myfilelink', function(error) {
|
||||
if(error) throw error;
|
||||
fs.lstat('/myfilelink', function(error, stats) {
|
||||
expect(stats.isDirectory()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isBlockDevice()', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isBlockDevice).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isBlockDevice()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isCharacterDevice()', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isCharacterDevice).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isCharacterDevice()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isSymbolicLink()', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isSymbolicLink).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for file', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
fs.fstat(fd, function(error, stats) {
|
||||
expect(stats.isSymbolicLink()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if stats are for directory', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isSymbolicLink()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return true if stats are for symbolic link', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w+', function(error, fd) {
|
||||
if(error) throw error;
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
fs.symlink('/myfile', '/myfilelink', function(error) {
|
||||
if(error) throw error;
|
||||
fs.lstat('/myfilelink', function(error, stats) {
|
||||
expect(stats.isSymbolicLink()).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isFIFO()', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isFIFO).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isFIFO()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isSocket()', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isSocket).to.be.a('function');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false', function(done) {
|
||||
var fs = util.fs();
|
||||
fs.stat('/', function(error, stats) {
|
||||
if(error) throw error;
|
||||
expect(stats.isSocket()).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('generated name property', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should correct return name for a file', function(done) {
|
||||
var fs = util.fs();
|
||||
var filepath = '/a';
|
||||
|
||||
fs.writeFile(filepath, 'data', function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.stat(filepath, function(err, stats) {
|
||||
if(err) throw err;
|
||||
|
||||
expect(stats.name).to.equal(Path.basename(filepath));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should correct return name for an fd', function(done) {
|
||||
var fs = util.fs();
|
||||
var filepath = '/a';
|
||||
|
||||
fs.open(filepath, 'w', function(err, fd) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.fstat(fd, function(err, stats) {
|
||||
if(err) throw err;
|
||||
|
||||
expect(stats.name).to.equal(Path.basename(filepath));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,17 +1,19 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.symlink', function () {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function () {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.symlink).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should return an error if part of the parent destination path does not exist', function (done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.symlink('/', '/tmp/mydir', function (error) {
|
||||
expect(error).to.exist;
|
||||
|
@ -21,7 +23,7 @@ describe('fs.symlink', function () {
|
|||
});
|
||||
|
||||
it('should return an error if the destination path already exists', function (done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.symlink('/tmp', '/', function (error) {
|
||||
expect(error).to.exist;
|
||||
|
@ -31,7 +33,7 @@ describe('fs.symlink', function () {
|
|||
});
|
||||
|
||||
it('should create a symlink', function (done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.symlink('/', '/myfile', function (error) {
|
||||
expect(error).not.to.exist;
|
||||
|
@ -44,10 +46,40 @@ describe('fs.symlink', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('should return the same node data for a file and symbolic link', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.writeFile('/file', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.stat('/file', function(error, stats1) {
|
||||
if(error) throw error;
|
||||
|
||||
|
||||
fs.symlink('/file', '/symlink', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.stat('/symlink', function(error, stats2) {
|
||||
if(error) throw error;
|
||||
|
||||
// The node names will differ, confirm and remove.
|
||||
expect(stats1.name).to.equal('file');
|
||||
delete stats1.name;
|
||||
expect(stats2.name).to.equal('symlink');
|
||||
delete stats2.name;
|
||||
|
||||
expect(stats2).to.deep.equal(stats1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/** Tests for fsPromises API */
|
||||
describe('fsPromises.symlink', function () {
|
||||
it('should return an error if destination path does not exist', function () {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.symlink('/', '/tmp/link')
|
||||
.catch(error => {
|
||||
|
@ -57,7 +89,7 @@ describe('fs.symlink', function () {
|
|||
});
|
||||
|
||||
it('should return an error if source path does not exist', function () {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.symlink('/tmp/myLink', '/myLink')
|
||||
.catch(error => {
|
||||
|
@ -67,7 +99,7 @@ describe('fs.symlink', function () {
|
|||
});
|
||||
|
||||
it('Promise should create a symlink of type DIRECTORY when directory provided', function () {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.symlink('/', '/myDirLink')
|
||||
.then(() => fsPromises.stat('/myDirLink'))
|
||||
|
@ -78,7 +110,7 @@ describe('fs.symlink', function () {
|
|||
});
|
||||
|
||||
it('Promise should create a symlink of type FILE when file provided', function () {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.writeFile('/myFile', 'data')
|
||||
.then(() => fsPromises.symlink('/myFile', '/myFileLink'))
|
||||
|
@ -90,7 +122,7 @@ describe('fs.symlink', function () {
|
|||
});
|
||||
|
||||
it('Promise should return an error if the destination path already exists', function () {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.symlink('/tmp', '/')
|
||||
.catch(error => {
|
||||
|
@ -108,7 +140,7 @@ describe('fsPromises.symlink', function () {
|
|||
|
||||
|
||||
it('should return an error if part of the parent destination path does not exist', () => {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.symlink('/', '/tmp/mydir')
|
||||
.catch(error => {
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
let util = require('../lib/test-utils.js');
|
||||
let expect = require('chai').expect;
|
||||
|
||||
describe('fs.unlink', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.unlink).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should remove a link to an existing file', function(done) {
|
||||
var fs = util.fs();
|
||||
var complete1, complete2;
|
||||
let fs = util.fs();
|
||||
let complete1, complete2;
|
||||
|
||||
function maybeDone() {
|
||||
if(complete1 && complete2) {
|
||||
|
@ -53,7 +53,7 @@ describe('fs.unlink', function() {
|
|||
});
|
||||
|
||||
it('should not follow symbolic links', function(done) {
|
||||
var fs = util.fs();
|
||||
let fs = util.fs();
|
||||
|
||||
fs.symlink('/', '/myFileLink', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -85,7 +85,7 @@ describe('fs.unlink', function() {
|
|||
});
|
||||
|
||||
it('should not unlink directories', function (done) {
|
||||
var fs = util.fs();
|
||||
let fs = util.fs();
|
||||
|
||||
fs.mkdir('/mydir', function (error) {
|
||||
if(error) throw error;
|
||||
|
@ -110,12 +110,12 @@ describe('fs.promises.unlink', function () {
|
|||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function () {
|
||||
var fs = util.fs();
|
||||
let fs = util.fs();
|
||||
expect(fs.promises.unlink).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should return an error if trying to delete a file that does not exist', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.unlink('/myFile')
|
||||
.catch(error => {
|
||||
|
@ -125,7 +125,7 @@ describe('fs.promises.unlink', function () {
|
|||
});
|
||||
|
||||
it('should not unlink directories', () => {
|
||||
var fs = util.fs().promises;
|
||||
let fs = util.fs().promises;
|
||||
|
||||
return fs.mkdir('/mydir')
|
||||
.then(() => fs.unlink('/mydir'))
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.watch', function() {
|
||||
// Our watch infrastucture is dependent on document.localStorage
|
||||
|
@ -16,14 +18,14 @@ describe('fs.watch', function() {
|
|||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(typeof fs.watch).to.equal('function');
|
||||
});
|
||||
|
||||
it('should get a change event when writing a file', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
var watcher = fs.watch('/myfile', function(event, filename) {
|
||||
const watcher = fs.watch('/myfile', function(event, filename) {
|
||||
expect(event).to.equal('change');
|
||||
expect(filename).to.equal('/myfile');
|
||||
watcher.close();
|
||||
|
@ -36,9 +38,9 @@ describe('fs.watch', function() {
|
|||
});
|
||||
|
||||
it('should get a change event when writing a file beneath root dir with recursive=true', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
var watcher = fs.watch('/', { recursive: true }, function(event, filename) {
|
||||
const watcher = fs.watch('/', { recursive: true }, function(event, filename) {
|
||||
expect(event).to.equal('change');
|
||||
expect(filename).to.equal('/');
|
||||
watcher.close();
|
||||
|
@ -51,12 +53,12 @@ describe('fs.watch', function() {
|
|||
});
|
||||
|
||||
it('should get a change event when writing a file in a dir with recursive=true', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/foo', function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
var watcher = fs.watch('/foo', { recursive: true }, function(event, filename) {
|
||||
const watcher = fs.watch('/foo', { recursive: true }, function(event, filename) {
|
||||
expect(event).to.equal('change');
|
||||
expect(filename).to.equal('/foo');
|
||||
watcher.close();
|
||||
|
@ -77,7 +79,7 @@ describe('fs.watch', function() {
|
|||
|
||||
// Bug to deal with this is filed at https://github.com/filerjs/filer/issues/594
|
||||
it.skip('should get a change event when a hardlink is watched and the original file is changed', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/myfile', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -85,7 +87,7 @@ describe('fs.watch', function() {
|
|||
fs.link('/myfile', '/hardlink', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
var watcher = fs.watch('/hardlink', function(event, filename) {
|
||||
const watcher = fs.watch('/hardlink', function(event, filename) {
|
||||
expect(event).to.equal('change');
|
||||
expect(filename).to.equal('/hardlink');
|
||||
|
||||
|
@ -107,14 +109,14 @@ describe('fs.watch', function() {
|
|||
});
|
||||
|
||||
it('should get a change event when renaming a file', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/myfile', 'data', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
//Normaly A 'rename' event should be thrown, but filer doesn't support that event at this time.
|
||||
//For now renaming a file will throw a change event.
|
||||
var watcher = fs.watch('/myfile', function(event, filename) {
|
||||
const watcher = fs.watch('/myfile', function(event, filename) {
|
||||
expect(event).to.equal('change');
|
||||
expect(filename).to.equal('/myfile');
|
||||
watcher.close();
|
||||
|
@ -126,4 +128,4 @@ describe('fs.watch', function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,28 +1,25 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.write', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.write).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should error if file path is undefined',function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.writeFile(undefined, 'data', function(error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('EINVAL');
|
||||
done();
|
||||
});
|
||||
it('should error if file path is undefined', function() {
|
||||
const fs = util.fs();
|
||||
const fn = () => fs.writeFile(undefined, 'data');
|
||||
expect(fn).to.throw();
|
||||
});
|
||||
|
||||
it('should write data to a file', function(done) {
|
||||
var fs = util.fs();
|
||||
var buffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
const fs = util.fs();
|
||||
const buffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
|
||||
fs.open('/myfile', 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
@ -35,16 +32,16 @@ describe('fs.write', function() {
|
|||
expect(error).not.to.exist;
|
||||
expect(result.isFile()).to.be.true;
|
||||
expect(result.size).to.equal(buffer.length);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update the current file position', function(done) {
|
||||
var fs = util.fs();
|
||||
var buffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
var _result = 0;
|
||||
const fs = util.fs();
|
||||
const buffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
let _result = 0;
|
||||
|
||||
fs.open('/myfile', 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
@ -62,10 +59,55 @@ describe('fs.write', function() {
|
|||
expect(error).not.to.exist;
|
||||
expect(_result).to.equal(2 * buffer.length);
|
||||
expect(result.size).to.equal(_result);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail if given a file path vs. an fd', function(done) {
|
||||
const fs = util.fs();
|
||||
const buffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
|
||||
fs.write('/myfile', buffer, 0, buffer.length, 0, function(error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('EBADF');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail when trying to write more bytes than are available in the buffer (length too long)', function(done) {
|
||||
const fs = util.fs();
|
||||
const buffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
|
||||
fs.open('/myfile', 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.write(fd, buffer, 0, (buffer.length + 10), 0, function(error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('EIO');
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail to write data to a file opened without the O_WRITE flag', function(done) {
|
||||
const fs = util.fs();
|
||||
const buffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
|
||||
fs.mknod('/myfile', 'FILE', function(err) {
|
||||
if (err) throw err;
|
||||
|
||||
fs.open('/myfile', 'r', function(error, fd) {
|
||||
if(error) throw error;
|
||||
|
||||
fs.write(fd, buffer, 0, buffer.length, 0, function(error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('EBADF');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.writeFile, fs.readFile', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.writeFile).to.be.a('function');
|
||||
expect(fs.readFile).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should error when path is wrong to readFile', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.readFile('/no-such-file', 'utf8', function(error, data) {
|
||||
expect(error).to.exist;
|
||||
|
@ -24,7 +25,7 @@ describe('fs.writeFile, fs.readFile', function() {
|
|||
|
||||
|
||||
it('should error when path is wrong to writeFile',function(done){
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/tmp/myfile', '','utf8', function(error, result) {
|
||||
expect(error).to.exist;
|
||||
|
@ -36,8 +37,8 @@ describe('fs.writeFile, fs.readFile', function() {
|
|||
});
|
||||
|
||||
it('should write, read a utf8 file without specifying utf8 in writeFile', function(done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
fs.writeFile('/myfile', contents, function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -50,8 +51,8 @@ describe('fs.writeFile, fs.readFile', function() {
|
|||
});
|
||||
|
||||
it('should write, read a utf8 file with "utf8" option to writeFile', function(done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
fs.writeFile('/myfile', contents, 'utf8', function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -64,8 +65,8 @@ describe('fs.writeFile, fs.readFile', function() {
|
|||
});
|
||||
|
||||
it('should write, read a utf8 file with {encoding: "utf8"} option to writeFile', function(done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
fs.writeFile('/myfile', contents, { encoding: 'utf8' }, function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -78,9 +79,9 @@ describe('fs.writeFile, fs.readFile', function() {
|
|||
});
|
||||
|
||||
it('should write, read a binary file', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
// String and utf8 binary encoded versions of the same thing: 'This is a file.'
|
||||
var binary = Buffer.from([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
|
||||
const binary = Buffer.from([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
|
||||
|
||||
fs.writeFile('/myfile', binary, function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -93,8 +94,8 @@ describe('fs.writeFile, fs.readFile', function() {
|
|||
});
|
||||
|
||||
it('should follow symbolic links', function(done) {
|
||||
var fs = util.fs();
|
||||
var contents = 'This is a file.';
|
||||
const fs = util.fs();
|
||||
const contents = 'This is a file.';
|
||||
|
||||
fs.writeFile('/myfile', '', { encoding: 'utf8' }, function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -122,16 +123,16 @@ describe('fsPromises.writeFile, fsPromises.readFile', function() {
|
|||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
expect(fsPromises.writeFile).to.be.a('function');
|
||||
expect(fsPromises.readFile).to.be.a('function');
|
||||
});
|
||||
|
||||
it('should return a promise', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
var contents = 'This is a file.';
|
||||
const fsPromises = util.fs().promises;
|
||||
const contents = 'This is a file.';
|
||||
|
||||
var p = fsPromises.writeFile('/myfile', contents);
|
||||
const p = fsPromises.writeFile('/myfile', contents);
|
||||
expect(p).to.be.a('Promise');
|
||||
|
||||
p.then(() => {
|
||||
|
@ -141,7 +142,7 @@ describe('fsPromises.writeFile, fsPromises.readFile', function() {
|
|||
});
|
||||
|
||||
it('should error when path is wrong to readFile', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
|
||||
return fsPromises.readFile('/no-such-file', 'utf8')
|
||||
.catch(error => {
|
||||
|
@ -151,8 +152,8 @@ describe('fsPromises.writeFile, fsPromises.readFile', function() {
|
|||
});
|
||||
|
||||
it('should write, read a utf8 file without specifying utf8 in writeFile', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
var contents = 'This is a file.';
|
||||
const fsPromises = util.fs().promises;
|
||||
const contents = 'This is a file.';
|
||||
|
||||
return fsPromises.writeFile('/myfile', contents)
|
||||
.then( () => fsPromises.readFile('/myfile', 'utf8'))
|
||||
|
@ -160,8 +161,8 @@ describe('fsPromises.writeFile, fsPromises.readFile', function() {
|
|||
});
|
||||
|
||||
it('should write, read a utf8 file with "utf8" option to writeFile', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
var contents = 'This is a file.';
|
||||
const fsPromises = util.fs().promises;
|
||||
const contents = 'This is a file.';
|
||||
|
||||
return fsPromises.writeFile('/myfile', contents, 'utf8')
|
||||
.then( () => fsPromises.readFile('/myfile', 'utf8'))
|
||||
|
@ -169,8 +170,8 @@ describe('fsPromises.writeFile, fsPromises.readFile', function() {
|
|||
});
|
||||
|
||||
it('should write, read a utf8 file with {encoding: "utf8"} option to writeFile', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
var contents = 'This is a file.';
|
||||
const fsPromises = util.fs().promises;
|
||||
const contents = 'This is a file.';
|
||||
|
||||
return fsPromises.writeFile('/myfile', contents, { encoding: 'utf8' })
|
||||
.then( () => fsPromises.readFile('/myfile', 'utf8'))
|
||||
|
@ -178,9 +179,9 @@ describe('fsPromises.writeFile, fsPromises.readFile', function() {
|
|||
});
|
||||
|
||||
it('should write, read a binary file', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
const fsPromises = util.fs().promises;
|
||||
// String and utf8 binary encoded versions of the same thing: 'This is a file.'
|
||||
var binary = Buffer.from([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
|
||||
const binary = Buffer.from([84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 105, 108, 101, 46]);
|
||||
|
||||
return fsPromises.writeFile('/myfile', binary)
|
||||
.then( () => fsPromises.readFile('/myfile'))
|
||||
|
@ -188,8 +189,8 @@ describe('fsPromises.writeFile, fsPromises.readFile', function() {
|
|||
});
|
||||
|
||||
it('should follow symbolic links', function() {
|
||||
var fsPromises = util.fs().promises;
|
||||
var contents = 'This is a file.';
|
||||
const fsPromises = util.fs().promises;
|
||||
const contents = 'This is a file.';
|
||||
|
||||
return fsPromises.writeFile('/myfile', '', { encoding: 'utf8' })
|
||||
.then( () => fsPromises.symlink('/myfile', '/myFileLink'))
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('fs.xattr', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should be a function', function () {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
expect(fs.setxattr).to.be.a('function');
|
||||
expect(fs.getxattr).to.be.a('function');
|
||||
expect(fs.removexattr).to.be.a('function');
|
||||
|
@ -15,7 +17,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should error when setting with a name that is not a string', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -29,7 +31,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should error when setting with a name that is null', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -43,7 +45,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should error when setting with an invalid flag', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -57,7 +59,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should error when when setting an extended attribute which exists with XATTR_CREATE flag', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function(error) {
|
||||
if (error) throw error;
|
||||
|
@ -75,7 +77,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should error when setting an extended attribute which does not exist with XATTR_REPLACE flag', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function(error) {
|
||||
if (error) throw error;
|
||||
|
@ -89,7 +91,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should error when getting an attribute with a name that is empty', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function(error) {
|
||||
if (error) throw error;
|
||||
|
@ -104,7 +106,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should error when getting an attribute where the name is not a string', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function(error) {
|
||||
if (error) throw error;
|
||||
|
@ -119,7 +121,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should error when getting an attribute that does not exist', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function(error) {
|
||||
if (error) throw error;
|
||||
|
@ -134,10 +136,10 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should error when file descriptor is invalid', function(done) {
|
||||
var fs = util.fs();
|
||||
var completeSet = false;
|
||||
var completeGet = false;
|
||||
var completeRemove = false;
|
||||
const fs = util.fs();
|
||||
let completeSet = false;
|
||||
let completeGet = false;
|
||||
let completeRemove = false;
|
||||
|
||||
function maybeDone() {
|
||||
if(completeSet && completeGet && completeRemove) {
|
||||
|
@ -170,8 +172,8 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should set and get an extended attribute of a path', function(done) {
|
||||
var fs = util.fs();
|
||||
var name = 'test';
|
||||
const fs = util.fs();
|
||||
const name = 'test';
|
||||
|
||||
fs.writeFile('/testfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -189,7 +191,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should error when attempting to remove a non-existing attribute', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -207,7 +209,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should set and get an empty string as a value', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -225,7 +227,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should set and get an extended attribute for a valid file descriptor', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/testfile', 'w', function (error, ofd) {
|
||||
if (error) throw error;
|
||||
|
@ -236,14 +238,14 @@ describe('fs.xattr', function() {
|
|||
fs.fgetxattr(ofd, 'test', function (error, value) {
|
||||
expect(error).not.to.exist;
|
||||
expect(value).to.equal('value');
|
||||
done();
|
||||
fs.close(ofd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should set and get an object to an extended attribute', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -261,7 +263,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should update/overwrite an existing extended attribute', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -296,7 +298,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should set multiple extended attributes for a path', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -323,7 +325,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should remove an extended attribute from a path', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -350,7 +352,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should remove an extended attribute from a valid file descriptor', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/testfile', 'w', function (error, ofd) {
|
||||
if (error) throw error;
|
||||
|
@ -368,7 +370,7 @@ describe('fs.xattr', function() {
|
|||
fs.fgetxattr(ofd, 'test', function (error) {
|
||||
expect(error).to.exist;
|
||||
expect(error.code).to.equal('ENOATTR');
|
||||
done();
|
||||
fs.close(ofd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -377,7 +379,7 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
|
||||
it('should allow setting with a null value', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.writeFile('/testfile', '', function (error) {
|
||||
if (error) throw error;
|
||||
|
@ -393,4 +395,4 @@ describe('fs.xattr', function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -9,23 +9,18 @@ describe('node.js tests: https://github.com/joyent/node/blob/master/test/simple/
|
|||
var checks = [];
|
||||
var fnCount = 0;
|
||||
var fnTotal = 16;
|
||||
var expected = 'Path must be a string without null bytes.';
|
||||
var fs = util.fs();
|
||||
|
||||
// Make sure function fails with null path error in callback.
|
||||
function check(fn) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
args = args.concat(function(err) {
|
||||
checks.push(function(){
|
||||
expect(err).to.exist;
|
||||
expect(err.message).to.equal(expected);
|
||||
});
|
||||
fnCount++;
|
||||
if(fnCount === fnTotal) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
fn.apply(fs, args);
|
||||
fn = () => fn.apply(fs, args);
|
||||
expect(fn).to.throw();
|
||||
|
||||
fnCount++;
|
||||
if(fnCount === fnTotal) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
check(fs.link, '/foo\u0000bar', 'foobar');
|
||||
|
|
|
@ -52,20 +52,30 @@ describe('node.js tests: https://github.com/joyent/node/blob/master/test/simple/
|
|||
|
||||
it('should allow watches on dirs', function(done) {
|
||||
var fs = util.fs();
|
||||
|
||||
fs.mkdir('/tmp', function(error) {
|
||||
if(error) throw error;
|
||||
var steps = 0;
|
||||
|
||||
function cleanup() {
|
||||
steps++;
|
||||
|
||||
if(steps === 2) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
var watcher = fs.watch('/tmp', function(event, filename) {
|
||||
// TODO: node thinks this should be 'rename', need to add rename along with change.
|
||||
expect(event).to.equal('change');
|
||||
expect(filename).to.equal('/tmp');
|
||||
watcher.close();
|
||||
done();
|
||||
cleanup();
|
||||
});
|
||||
|
||||
fs.open('/tmp/newfile.txt', 'w', function(error, fd) {
|
||||
if(error) throw error;
|
||||
fs.close(fd);
|
||||
fs.close(fd, cleanup);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
var Filer = require('../../src');
|
||||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
const Filer = require('../../src');
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
// Support global URL and node's url module
|
||||
const URL = global.URL || require('url').URL;
|
||||
|
||||
describe('path resolution', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should follow a symbolic link to the root directory', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.symlink('/', '/mydirectorylink', function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -16,7 +20,7 @@ describe('path resolution', function() {
|
|||
if(error) throw error;
|
||||
|
||||
expect(result['node']).to.exist;
|
||||
var _node = result['node'];
|
||||
const _node = result['node'];
|
||||
|
||||
fs.stat('/mydirectorylink', function(error, result) {
|
||||
expect(error).not.to.exist;
|
||||
|
@ -29,7 +33,7 @@ describe('path resolution', function() {
|
|||
});
|
||||
|
||||
it('should follow a symbolic link to a directory', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/mydir', function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -41,7 +45,7 @@ describe('path resolution', function() {
|
|||
if(error) throw error;
|
||||
|
||||
expect(result['node']).to.exist;
|
||||
var _node = result['node'];
|
||||
const _node = result['node'];
|
||||
fs.stat('/mydirectorylink', function(error, result) {
|
||||
expect(error).not.to.exist;
|
||||
expect(result).to.exist;
|
||||
|
@ -54,18 +58,18 @@ describe('path resolution', function() {
|
|||
});
|
||||
|
||||
it('should follow a symbolic link to a file', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w', function(error, result) {
|
||||
if(error) throw error;
|
||||
var fd = result;
|
||||
const fd = result;
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
fs.stat('/myfile', function(error, result) {
|
||||
if(error) throw error;
|
||||
|
||||
expect(result['node']).to.exist;
|
||||
var _node = result['node'];
|
||||
const _node = result['node'];
|
||||
fs.symlink('/myfile', '/myfilelink', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
|
@ -82,18 +86,18 @@ describe('path resolution', function() {
|
|||
});
|
||||
|
||||
it('should follow multiple symbolic links to a file', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w', function(error, result) {
|
||||
if(error) throw error;
|
||||
var fd = result;
|
||||
const fd = result;
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
fs.stat('/myfile', function(error, result) {
|
||||
if(error) throw error;
|
||||
|
||||
expect(result['node']).to.exist;
|
||||
var _node = result['node'];
|
||||
const _node = result['node'];
|
||||
fs.symlink('/myfile', '/myfilelink1', function(error) {
|
||||
if(error) throw error;
|
||||
fs.symlink('/myfilelink1', '/myfilelink2', function(error) {
|
||||
|
@ -113,7 +117,7 @@ describe('path resolution', function() {
|
|||
});
|
||||
|
||||
it('should error if symbolic link leads to itself', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.symlink('/mylink1', '/mylink2', function(error) {
|
||||
if(error) throw error;
|
||||
|
@ -132,8 +136,8 @@ describe('path resolution', function() {
|
|||
});
|
||||
|
||||
it('should error if it follows more than 10 symbolic links', function(done) {
|
||||
var fs = util.fs();
|
||||
var nlinks = 11;
|
||||
const fs = util.fs();
|
||||
const nlinks = 11;
|
||||
|
||||
function createSymlinkChain(n, callback) {
|
||||
if(n > nlinks) {
|
||||
|
@ -145,7 +149,7 @@ describe('path resolution', function() {
|
|||
|
||||
fs.open('/myfile0', 'w', function(error, result) {
|
||||
if(error) throw error;
|
||||
var fd = result;
|
||||
const fd = result;
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
fs.stat('/myfile0', function(error, result) {
|
||||
|
@ -167,17 +171,17 @@ describe('path resolution', function() {
|
|||
});
|
||||
|
||||
it('should follow a symbolic link in the path to a file', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w', function(error, result) {
|
||||
if(error) throw error;
|
||||
var fd = result;
|
||||
const fd = result;
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
fs.stat('/myfile', function(error, result) {
|
||||
if(error) throw error;
|
||||
|
||||
var _node = result['node'];
|
||||
const _node = result['node'];
|
||||
fs.symlink('/', '/mydirlink', function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
|
@ -195,11 +199,11 @@ describe('path resolution', function() {
|
|||
});
|
||||
|
||||
it('should error if a symbolic link in the path to a file is itself a file', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
fs.open('/myfile', 'w', function(error, result) {
|
||||
if(error) throw error;
|
||||
var fd = result;
|
||||
const fd = result;
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
fs.stat('/myfile', function(error, result) {
|
||||
|
@ -208,7 +212,7 @@ describe('path resolution', function() {
|
|||
|
||||
fs.open('/myfile2', 'w', function(error, result) {
|
||||
if(error) throw error;
|
||||
var fd = result;
|
||||
const fd = result;
|
||||
fs.close(fd, function(error) {
|
||||
if(error) throw error;
|
||||
fs.symlink('/myfile2', '/mynotdirlink', function(error) {
|
||||
|
@ -229,7 +233,7 @@ describe('path resolution', function() {
|
|||
});
|
||||
|
||||
it('should properly add trailing slashes with Path.addTrailing()', function() {
|
||||
var Path = Filer.Path;
|
||||
const Path = Filer.Path;
|
||||
expect(Path.addTrailing('/')).to.equal('/');
|
||||
expect(Path.addTrailing('/////')).to.equal('/');
|
||||
expect(Path.addTrailing('.')).to.equal('./');
|
||||
|
@ -238,11 +242,59 @@ describe('path resolution', function() {
|
|||
});
|
||||
|
||||
it('should properly remove trailing slashes with Path.removeTrailing()', function() {
|
||||
var Path = Filer.Path;
|
||||
const Path = Filer.Path;
|
||||
expect(Path.removeTrailing('/')).to.equal('/');
|
||||
expect(Path.removeTrailing('/////')).to.equal('/');
|
||||
expect(Path.removeTrailing('./')).to.equal('.');
|
||||
expect(Path.removeTrailing('/dir/')).to.equal('/dir');
|
||||
expect(Path.removeTrailing('/dir//')).to.equal('/dir');
|
||||
});
|
||||
|
||||
it('should allow using Buffer for paths', function(done) {
|
||||
const fs = util.fs();
|
||||
const filePath = '/file';
|
||||
const bufferPath = Buffer.from(filePath);
|
||||
const data = 'data';
|
||||
|
||||
fs.writeFile(bufferPath, data, function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.readFile(filePath, 'utf8', function(err, result) {
|
||||
if(err) throw err;
|
||||
expect(result).to.equal(data);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow using file: URLs for paths', function(done) {
|
||||
const fs = util.fs();
|
||||
const filePath = '/file';
|
||||
const fileUrl = new URL(`file://${filePath}`);
|
||||
const data = 'data';
|
||||
|
||||
fs.writeFile(fileUrl, data, function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
fs.readFile(filePath, 'utf8', function(err, result) {
|
||||
if(err) throw err;
|
||||
expect(result).to.equal(data);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should error for non file: URLs for paths', function() {
|
||||
const fs = util.fs();
|
||||
const fileUrl = new URL('http://file');
|
||||
const fn = () => fs.writeFile(fileUrl, 1);
|
||||
expect(fn).to.throw();
|
||||
});
|
||||
|
||||
it('should error if file: URLs include escaped / characters', function() {
|
||||
const fs = util.fs();
|
||||
const fileUrl = new URL('file:///p/a/t/h/%2F');
|
||||
const fn = () => fs.writeFile(fileUrl, 1);
|
||||
expect(fn).to.throw();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,10 +10,6 @@ describe('Filer.FileSystem.providers', function() {
|
|||
expect(Filer.FileSystem.providers.IndexedDB).to.be.a('function');
|
||||
});
|
||||
|
||||
it('has WebSQL constructor', function() {
|
||||
expect(Filer.FileSystem.providers.WebSQL).to.be.a('function');
|
||||
});
|
||||
|
||||
it('has Memory constructor', function() {
|
||||
expect(Filer.FileSystem.providers.Memory).to.be.a('function');
|
||||
});
|
||||
|
@ -21,8 +17,4 @@ describe('Filer.FileSystem.providers', function() {
|
|||
it('has a Default constructor', function() {
|
||||
expect(Filer.FileSystem.providers.Default).to.be.a('function');
|
||||
});
|
||||
|
||||
it('has Fallback constructor', function() {
|
||||
expect(Filer.FileSystem.providers.Fallback).to.be.a('function');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
var util = require('../../lib/test-utils.js');
|
||||
var providerBase = require('./providers.base.js');
|
||||
|
||||
providerBase('WebSQL', util.providers.WebSQL);
|
|
@ -0,0 +1,43 @@
|
|||
const { path } = require('../../src');
|
||||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
|
||||
describe('README example code', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
it('should run the code in the README overview example', function(done) {
|
||||
// Slightly modified version of the first example code in the README
|
||||
// See <a name="overviewExample"></a>
|
||||
const fs = util.fs();
|
||||
|
||||
fs.mkdir('/docs', (err) => {
|
||||
if (err) throw err;
|
||||
|
||||
const filename = path.join('/docs', 'first.txt');
|
||||
const data = 'Hello World!\n';
|
||||
|
||||
fs.writeFile(filename, data, (err) => {
|
||||
if (err) throw err;
|
||||
|
||||
fs.stat(filename, (err, stats) => {
|
||||
if (err) throw err;
|
||||
expect(stats.size).to.equal(data.length);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should run the fsPromises example code', function() {
|
||||
const fs = util.fs().promises;
|
||||
const filename = '/myfile';
|
||||
const data = 'some data';
|
||||
|
||||
return fs.writeFile(filename, data)
|
||||
.then(() => fs.stat(filename))
|
||||
.then(stats => {
|
||||
expect(stats.size).to.equal(data.length);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -30,6 +30,18 @@ describe('FileSystemShell.mkdirp', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should succeed if provided path is root, given as a relative path (\'.\' in \'/\')', function(done) {
|
||||
var fs = util.fs();
|
||||
var shell = new fs.Shell();
|
||||
shell.cd('/', function(err) {
|
||||
expect(err).to.not.exist;
|
||||
shell.mkdirp('.', function(err) {
|
||||
expect(err).to.not.exist;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should succeed if the directory exists', function(done) {
|
||||
var fs = util.fs();
|
||||
var shell = new fs.Shell();
|
||||
|
@ -67,6 +79,21 @@ describe('FileSystemShell.mkdirp', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should succeed on a folder given as a relative path (\'test\' in \'/\')', function(done) {
|
||||
var fs = util.fs();
|
||||
var shell = new fs.Shell();
|
||||
shell.cd('/', function(err) {
|
||||
expect(err).to.not.exist;
|
||||
shell.mkdirp('test', function(err) {
|
||||
expect(err).to.not.exist;
|
||||
fs.exists('/test', function(dir){
|
||||
expect(dir).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should succeed on a folder with a nonexistant parent (\'/test/test\')', function(done) {
|
||||
var fs = util.fs();
|
||||
var shell = new fs.Shell();
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
'use strict';
|
||||
const expect = require('chai').expect;
|
||||
const utils = require('../../lib/test-utils');
|
||||
const fs = utils.shimIndexedDB(() => require('../../../shims/fs'));
|
||||
|
||||
describe('fs shim', () => {
|
||||
it('should be defined', () => {
|
||||
expect(fs).to.not.be.undefined;
|
||||
});
|
||||
|
||||
it('should be an object', () => {
|
||||
expect(typeof fs).to.equal('object');
|
||||
});
|
||||
|
||||
it('should return a function when accessing fs.writeFile', () => {
|
||||
expect(typeof fs.writeFile).to.equal('function');
|
||||
});
|
||||
|
||||
it('should call callback when calling fs.writeFile', (done) => {
|
||||
fs.writeFile('/test.txt', 'test', function(err) {
|
||||
if(err) throw err;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an object when accessing fs.promises', () => {
|
||||
expect(typeof fs.promises).to.equal('object');
|
||||
});
|
||||
|
||||
it('should return a function when accessing fs.promises.writeFile', () => {
|
||||
expect(typeof fs.promises.writeFile).to.equal('function');
|
||||
});
|
||||
|
||||
it('should return a promise which resolves when calling fs.promises.writeFile', (done) => {
|
||||
const writeFilePromise = fs.promises.writeFile('/test2.txt', '');
|
||||
expect(writeFilePromise instanceof Promise).to.equal(true);
|
||||
writeFilePromise.then(() => {
|
||||
done();
|
||||
}).catch((err) => {
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,14 @@
|
|||
'use strict';
|
||||
const expect = require('chai').expect;
|
||||
const path = require('../../../shims/path');
|
||||
const pathActual = require('../../../src/index').path;
|
||||
|
||||
describe('path shim', () => {
|
||||
it('should be defined', () => {
|
||||
expect(path).to.not.be.undefined;
|
||||
});
|
||||
|
||||
it('should be re-exposing path', () => {
|
||||
expect(path).to.equal(pathActual);
|
||||
});
|
||||
});
|
|
@ -1,14 +1,16 @@
|
|||
var Filer = require('../../src');
|
||||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
|
||||
const Filer = require('../../src');
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('node times (atime, mtime, ctime) with mount flags', function() {
|
||||
|
||||
var dirname = '/dir';
|
||||
var filename = '/dir/file';
|
||||
const dirname = '/dir';
|
||||
const filename = '/dir/file';
|
||||
|
||||
function memoryFS(flags, callback) {
|
||||
var name = util.uniqueName();
|
||||
const name = util.uniqueName();
|
||||
return new Filer.FileSystem({
|
||||
name: name,
|
||||
flags: flags || [],
|
||||
|
@ -44,7 +46,7 @@ describe('node times (atime, mtime, ctime) with mount flags', function() {
|
|||
|
||||
it('should not update ctime when calling fs.rename() with NOCTIME', function(done) {
|
||||
memoryFS(['NOCTIME'], function(error, fs) {
|
||||
var newfilename = filename + '1';
|
||||
const newfilename = filename + '1';
|
||||
|
||||
createTree(fs, function() {
|
||||
stat(fs, filename, function(stats1) {
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
var util = require('../lib/test-utils.js');
|
||||
var expect = require('chai').expect;
|
||||
'use strict';
|
||||
const util = require('../lib/test-utils.js');
|
||||
const expect = require('chai').expect;
|
||||
|
||||
describe('node times (atime, mtime, ctimeMs)', function() {
|
||||
beforeEach(util.setup);
|
||||
afterEach(util.cleanup);
|
||||
|
||||
var dirname = '/dir';
|
||||
var filename = '/dir/file';
|
||||
const dirname = '/dir';
|
||||
const filename = '/dir/file';
|
||||
|
||||
function createTree(callback) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
fs.mkdir(dirname, function(error) {
|
||||
if(error) throw error;
|
||||
|
||||
|
@ -22,7 +23,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
}
|
||||
|
||||
function stat(path, callback) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
fs.stat(path, function(error, stats) {
|
||||
if(error) throw error;
|
||||
|
||||
|
@ -31,8 +32,8 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
}
|
||||
|
||||
it('should update ctime when calling fs.rename()', function(done) {
|
||||
var fs = util.fs();
|
||||
var newfilename = filename + '1';
|
||||
const fs = util.fs();
|
||||
const newfilename = filename + '1';
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -52,7 +53,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update ctime, mtime, atime when calling fs.truncate()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -72,7 +73,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update ctime, mtime, atime when calling fs.ftruncate()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -97,7 +98,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.stat()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -115,7 +116,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.fstat()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -138,7 +139,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.lstat()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.link(filename, '/link', function(error) {
|
||||
|
@ -159,7 +160,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.exists()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -181,7 +182,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update ctime, atime when calling fs.link()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -200,7 +201,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.symlink()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -219,7 +220,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.readlink()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.symlink(filename, '/link', function(error) {
|
||||
|
@ -243,7 +244,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update ctime, atime, mtime of parent dir when calling fs.unlink()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(dirname, function(stats1) {
|
||||
|
@ -262,7 +263,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update ctime, atime, mtime of parent dir when calling fs.rmdir()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat('/', function(stats1) {
|
||||
|
@ -286,7 +287,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update ctime, atime, mtime of parent dir when calling fs.mkdir()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat('/', function(stats1) {
|
||||
|
@ -306,7 +307,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.close()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
|
@ -329,7 +330,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.open()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -353,8 +354,8 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
*/
|
||||
|
||||
it('should update atime, ctime, mtime when calling fs.write()', function(done) {
|
||||
var fs = util.fs();
|
||||
var buffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
const fs = util.fs();
|
||||
const buffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
|
||||
createTree(function() {
|
||||
fs.open('/myfile', 'w', function(error, fd) {
|
||||
|
@ -382,8 +383,8 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.read()', function(done) {
|
||||
var fs = util.fs();
|
||||
var buffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
const fs = util.fs();
|
||||
const buffer = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
|
||||
createTree(function() {
|
||||
fs.open('/myfile', 'w', function(err, fd) {
|
||||
|
@ -400,7 +401,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
if(error) throw error;
|
||||
|
||||
stat('/myfile', function(stats1) {
|
||||
var buffer2 = Buffer.alloc(buffer.length);
|
||||
const buffer2 = Buffer.alloc(buffer.length);
|
||||
|
||||
fs.read(fd, buffer2, 0, buffer2.length, 0, function(err, nbytes) {
|
||||
if(err) throw err;
|
||||
|
@ -426,7 +427,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.readFile()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -446,7 +447,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update atime, ctime, mtime when calling fs.writeFile()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -465,7 +466,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update atime, ctime, mtime when calling fs.appendFile()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -484,7 +485,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update ctime, atime when calling fs.setxattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
stat(filename, function(stats1) {
|
||||
|
@ -503,7 +504,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update ctime, atime when calling fs.fsetxattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
|
@ -517,7 +518,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
expect(stats2.ctimeMs).to.be.at.least(stats1.ctimeMs);
|
||||
expect(stats2.mtimeMs).to.equal(stats1.mtimeMs);
|
||||
expect(stats2.atimeMs).to.be.at.least(stats1.atimeMs);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -526,7 +527,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.getxattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.setxattr(filename, 'extra', 'data', function(error) {
|
||||
|
@ -550,7 +551,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should make no change when calling fs.fgetxattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
|
@ -568,7 +569,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
expect(stats2.ctimeMs).to.equal(stats1.ctimeMs);
|
||||
expect(stats2.mtimeMs).to.equal(stats1.mtimeMs);
|
||||
expect(stats2.atimeMs).to.equal(stats1.atimeMs);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -578,7 +579,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update ctime, atime when calling fs.removexattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.setxattr(filename, 'extra', 'data', function(error) {
|
||||
|
@ -601,7 +602,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
});
|
||||
|
||||
it('should update ctime, atime when calling fs.fremovexattr()', function(done) {
|
||||
var fs = util.fs();
|
||||
const fs = util.fs();
|
||||
|
||||
createTree(function() {
|
||||
fs.open(filename, 'w', function(error, fd) {
|
||||
|
@ -618,7 +619,7 @@ describe('node times (atime, mtime, ctimeMs)', function() {
|
|||
expect(stats2.ctimeMs).to.be.at.least(stats1.ctimeMs);
|
||||
expect(stats2.mtimeMs).to.equal(stats1.mtimeMs);
|
||||
expect(stats2.atimeMs).to.be.at.least(stats1.atimeMs);
|
||||
done();
|
||||
fs.close(fd, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,528 @@
|
|||
'use strict';
|
||||
const expect = require('chai').expect;
|
||||
const utils = require('../../lib/test-utils');
|
||||
const FilerWebpackPlugin = require('../../../src/webpack-plugin');
|
||||
|
||||
function createNMFResolveCompilerObject(resolveData) {
|
||||
|
||||
const normalModuleFactory_resolve_tap = utils.createMockFn(function (name, callback) {
|
||||
callback(resolveData);
|
||||
});
|
||||
|
||||
const normalModuleFactory = {
|
||||
hooks: {
|
||||
resolve: {
|
||||
tap: normalModuleFactory_resolve_tap
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const normalModuleFactory_tap = utils.createMockFn(function (name, callback) {
|
||||
callback(normalModuleFactory);
|
||||
});
|
||||
|
||||
const compiler = {
|
||||
hooks: {
|
||||
normalModuleFactory: {
|
||||
tap: normalModuleFactory_tap,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
compiler,
|
||||
normalModuleFactory_tap,
|
||||
normalModuleFactory_resolve_tap,
|
||||
};
|
||||
}
|
||||
|
||||
describe('path shim', () => {
|
||||
it('should instantiate the plugin with valid options', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: false,
|
||||
shimPath: false,
|
||||
fsProvider: 'custom',
|
||||
};
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
|
||||
// Assert
|
||||
expect(plugin.options).to.not.be.undefined;
|
||||
|
||||
expect(plugin.options.filerDir).to.equal(options.filerDir);
|
||||
expect(plugin.options.shimsDir).to.equal(options.shimsDir);
|
||||
expect(plugin.options.fsProviderDir).to.equal(options.fsProviderDir);
|
||||
expect(plugin.options.shimFs).to.equal(options.shimFs);
|
||||
expect(plugin.options.shimPath).to.equal(options.shimPath);
|
||||
expect(plugin.options.fsProvider).to.equal(options.fsProvider);
|
||||
});
|
||||
|
||||
it('should instantiate the plugin with default options', () => {
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin();
|
||||
|
||||
// Assert
|
||||
expect(plugin.options).to.not.be.undefined;
|
||||
|
||||
expect(plugin.options.filerDir).to.equal('/node_modules/filer');
|
||||
expect(plugin.options.shimsDir).to.equal('/node_modules/filer/shims');
|
||||
expect(plugin.options.fsProviderDir).to.equal('/node_modules/filer/shims/providers');
|
||||
expect(plugin.options.shimFs).to.equal(true);
|
||||
expect(plugin.options.shimPath).to.equal(true);
|
||||
expect(plugin.options.fsProvider).to.equal('default');
|
||||
});
|
||||
|
||||
it('should throw if provided invalid options', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: 123,
|
||||
shimsDir: 456,
|
||||
fsProviderDir: 789,
|
||||
shimFs: 'false',
|
||||
shimPath: 'false',
|
||||
fsProvider: false,
|
||||
};
|
||||
|
||||
// Act // Assert
|
||||
expect(() => {
|
||||
new FilerWebpackPlugin(options);
|
||||
}).to.throw();
|
||||
});
|
||||
|
||||
it('should instantiate the plugin with options and the <rootDir> tag should be replaced', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '<rootDir>/filer',
|
||||
shimsDir: '<rootDir>/shims',
|
||||
fsProviderDir: '<rootDir>/fsProvider',
|
||||
};
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
|
||||
// Assert
|
||||
expect(plugin.options).to.not.be.undefined;
|
||||
|
||||
expect(plugin.options.filerDir).to.equal(options.filerDir.replace('<rootDir>', ''));
|
||||
expect(plugin.options.shimsDir).to.equal(options.shimsDir.replace('<rootDir>', ''));
|
||||
expect(plugin.options.fsProviderDir).to.equal(options.fsProviderDir.replace('<rootDir>', ''));
|
||||
});
|
||||
|
||||
describe('should instantiate the plugin with valid options and invoke the apply method', () => {
|
||||
it('should ignore an unrelated module', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: false,
|
||||
shimPath: false,
|
||||
fsProvider: 'custom',
|
||||
};
|
||||
|
||||
const resolveData = {
|
||||
request: 'aModuleWeDontCareAbout',
|
||||
context: '/some/random/directory',
|
||||
};
|
||||
const resolveDataIn = Object.create(resolveData);
|
||||
|
||||
// Mocks
|
||||
const {
|
||||
compiler,
|
||||
normalModuleFactory_tap,
|
||||
normalModuleFactory_resolve_tap,
|
||||
} = createNMFResolveCompilerObject(resolveDataIn);
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
plugin.apply(compiler);
|
||||
|
||||
// Assert
|
||||
expect(normalModuleFactory_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(normalModuleFactory_resolve_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_resolve_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(resolveDataIn.request).to.equal(resolveData.request);
|
||||
});
|
||||
|
||||
it('should resolve fsProvider to <fsProviderDir>/default.js when fsProvider options is default', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: false,
|
||||
shimPath: false,
|
||||
fsProvider: 'default',
|
||||
};
|
||||
|
||||
const resolveData = {
|
||||
request: 'fsProvider',
|
||||
context: options.shimsDir,
|
||||
};
|
||||
const resolveDataIn = Object.create(resolveData);
|
||||
|
||||
// Mocks
|
||||
const {
|
||||
compiler,
|
||||
normalModuleFactory_tap,
|
||||
normalModuleFactory_resolve_tap,
|
||||
} = createNMFResolveCompilerObject(resolveDataIn);
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
plugin.apply(compiler);
|
||||
|
||||
// Assert
|
||||
expect(normalModuleFactory_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(normalModuleFactory_resolve_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_resolve_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(resolveDataIn.request).to.equal(`${options.fsProviderDir}/default.js`);
|
||||
});
|
||||
|
||||
it('should resolve fsProvider to <fsProviderDir>/indexeddb.js when fsProvider options is indexeddb', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: false,
|
||||
shimPath: false,
|
||||
fsProvider: 'indexeddb',
|
||||
};
|
||||
|
||||
const resolveData = {
|
||||
request: 'fsProvider',
|
||||
context: options.shimsDir,
|
||||
};
|
||||
const resolveDataIn = Object.create(resolveData);
|
||||
|
||||
// Mocks
|
||||
const {
|
||||
compiler,
|
||||
normalModuleFactory_tap,
|
||||
normalModuleFactory_resolve_tap,
|
||||
} = createNMFResolveCompilerObject(resolveDataIn);
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
plugin.apply(compiler);
|
||||
|
||||
// Assert
|
||||
expect(normalModuleFactory_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(normalModuleFactory_resolve_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_resolve_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(resolveDataIn.request).to.equal(`${options.fsProviderDir}/indexeddb.js`);
|
||||
});
|
||||
|
||||
it('should resolve fsProvider to <fsProviderDir>/memory.js when fsProvider options is memory', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: false,
|
||||
shimPath: false,
|
||||
fsProvider: 'memory',
|
||||
};
|
||||
|
||||
const resolveData = {
|
||||
request: 'fsProvider',
|
||||
context: options.shimsDir,
|
||||
};
|
||||
const resolveDataIn = Object.create(resolveData);
|
||||
|
||||
// Mocks
|
||||
const {
|
||||
compiler,
|
||||
normalModuleFactory_tap,
|
||||
normalModuleFactory_resolve_tap,
|
||||
} = createNMFResolveCompilerObject(resolveDataIn);
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
plugin.apply(compiler);
|
||||
|
||||
// Assert
|
||||
expect(normalModuleFactory_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(normalModuleFactory_resolve_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_resolve_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(resolveDataIn.request).to.equal(`${options.fsProviderDir}/memory.js`);
|
||||
});
|
||||
|
||||
it('should resolve fsProvider to <fsProviderDir>/custom.js when fsProvider options is custom', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: false,
|
||||
shimPath: false,
|
||||
fsProvider: 'custom',
|
||||
};
|
||||
|
||||
const resolveData = {
|
||||
request: 'fsProvider',
|
||||
context: options.shimsDir,
|
||||
};
|
||||
const resolveDataIn = Object.create(resolveData);
|
||||
|
||||
// Mocks
|
||||
const {
|
||||
compiler,
|
||||
normalModuleFactory_tap,
|
||||
normalModuleFactory_resolve_tap,
|
||||
} = createNMFResolveCompilerObject(resolveDataIn);
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
plugin.apply(compiler);
|
||||
|
||||
// Assert
|
||||
expect(normalModuleFactory_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(normalModuleFactory_resolve_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_resolve_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(resolveDataIn.request).to.equal(`${options.fsProviderDir}/custom.js`);
|
||||
});
|
||||
|
||||
it('should throw an error when an invalid options is provided for fsProvider', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: false,
|
||||
shimPath: false,
|
||||
fsProvider: 'invalid_fs_provider_option',
|
||||
};
|
||||
|
||||
const resolveData = {
|
||||
request: 'fsProvider',
|
||||
context: options.shimsDir,
|
||||
};
|
||||
const resolveDataIn = Object.create(resolveData);
|
||||
|
||||
// Mocks
|
||||
const {
|
||||
compiler,
|
||||
} = createNMFResolveCompilerObject(resolveDataIn);
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
|
||||
// Act // Assert
|
||||
expect(() => {
|
||||
plugin.apply(compiler);
|
||||
}).to.throw();
|
||||
});
|
||||
|
||||
it('should ignore a request for fs when the context is in the filer directory', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: false,
|
||||
shimPath: false,
|
||||
fsProvider: 'custom',
|
||||
};
|
||||
|
||||
const resolveData = {
|
||||
request: 'fs',
|
||||
context: options.filerDir + '/src',
|
||||
};
|
||||
const resolveDataIn = Object.create(resolveData);
|
||||
|
||||
// Mocks
|
||||
const {
|
||||
compiler,
|
||||
normalModuleFactory_tap,
|
||||
normalModuleFactory_resolve_tap,
|
||||
} = createNMFResolveCompilerObject(resolveDataIn);
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
plugin.apply(compiler);
|
||||
|
||||
// Assert
|
||||
expect(normalModuleFactory_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(normalModuleFactory_resolve_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_resolve_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(resolveDataIn.request).to.equal(resolveData.request);
|
||||
});
|
||||
|
||||
it('should resolve a request for fs to the fs shim when the context is not in the filer directory', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: true,
|
||||
shimPath: true,
|
||||
fsProvider: 'custom',
|
||||
};
|
||||
|
||||
const resolveData = {
|
||||
request: 'fs',
|
||||
context: '/some/random/directory',
|
||||
};
|
||||
const resolveDataIn = Object.create(resolveData);
|
||||
|
||||
// Mocks
|
||||
const {
|
||||
compiler,
|
||||
normalModuleFactory_tap,
|
||||
normalModuleFactory_resolve_tap,
|
||||
} = createNMFResolveCompilerObject(resolveDataIn);
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
plugin.apply(compiler);
|
||||
|
||||
// Assert
|
||||
expect(normalModuleFactory_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(normalModuleFactory_resolve_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_resolve_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(resolveDataIn.request).to.equal(`${options.shimsDir}/fs.js`);
|
||||
});
|
||||
|
||||
it('should not resolve a request for fs to the fs shim when the context is not in the filer directory but shimFs is false', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: false,
|
||||
shimPath: false,
|
||||
fsProvider: 'custom',
|
||||
};
|
||||
|
||||
const resolveData = {
|
||||
request: 'fs',
|
||||
context: '/some/random/directory',
|
||||
};
|
||||
const resolveDataIn = Object.create(resolveData);
|
||||
|
||||
// Mocks
|
||||
const {
|
||||
compiler,
|
||||
normalModuleFactory_tap,
|
||||
normalModuleFactory_resolve_tap,
|
||||
} = createNMFResolveCompilerObject(resolveDataIn);
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
plugin.apply(compiler);
|
||||
|
||||
// Assert
|
||||
expect(normalModuleFactory_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(normalModuleFactory_resolve_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_resolve_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(resolveDataIn.request).to.equal(resolveData.request);
|
||||
});
|
||||
|
||||
it('should resolve a request for path to the path shim when the context is not in the filer directory', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: true,
|
||||
shimPath: true,
|
||||
fsProvider: 'custom',
|
||||
};
|
||||
|
||||
const resolveData = {
|
||||
request: 'path',
|
||||
context: '/some/random/directory',
|
||||
};
|
||||
const resolveDataIn = Object.create(resolveData);
|
||||
|
||||
// Mocks
|
||||
const {
|
||||
compiler,
|
||||
normalModuleFactory_tap,
|
||||
normalModuleFactory_resolve_tap,
|
||||
} = createNMFResolveCompilerObject(resolveDataIn);
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
plugin.apply(compiler);
|
||||
|
||||
// Assert
|
||||
expect(normalModuleFactory_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(normalModuleFactory_resolve_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_resolve_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(resolveDataIn.request).to.equal(`${options.shimsDir}/path.js`);
|
||||
});
|
||||
|
||||
it('should not resolve a request for path to the path shim when the context is not in the filer directory but shimPath is false', () => {
|
||||
// Arrange
|
||||
const options = {
|
||||
filerDir: '/filer',
|
||||
shimsDir: '/shims',
|
||||
fsProviderDir: '/fsProvider',
|
||||
shimFs: false,
|
||||
shimPath: false,
|
||||
fsProvider: 'custom',
|
||||
};
|
||||
|
||||
const resolveData = {
|
||||
request: 'path',
|
||||
context: '/some/random/directory',
|
||||
};
|
||||
const resolveDataIn = Object.create(resolveData);
|
||||
|
||||
// Mocks
|
||||
const {
|
||||
compiler,
|
||||
normalModuleFactory_tap,
|
||||
normalModuleFactory_resolve_tap,
|
||||
} = createNMFResolveCompilerObject(resolveDataIn);
|
||||
|
||||
// Act
|
||||
const plugin = new FilerWebpackPlugin(options);
|
||||
plugin.apply(compiler);
|
||||
|
||||
// Assert
|
||||
expect(normalModuleFactory_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(normalModuleFactory_resolve_tap.calls).to.have.length(1);
|
||||
expect(normalModuleFactory_resolve_tap.calls[0].args[0]).to.equal('filer-webpack-plugin');
|
||||
|
||||
expect(resolveDataIn.request).to.equal(resolveData.request);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env node
|
||||
/* eslint-disable no-console */
|
||||
'use strict';
|
||||
|
||||
const {spawn} = require('child_process');
|
||||
const meow = require('meow');
|
||||
|
||||
const cli = meow(`
|
||||
Usage
|
||||
$ get-filer-version <SHA|branch|tag> [--out path/to/filer.js]
|
||||
|
||||
Options
|
||||
--out, -o Specify a Filer module path to use for output
|
||||
|
||||
Examples
|
||||
$ get-filer-version v0.0.44
|
||||
$ get-filer-version v0.0.44 --out filer.js
|
||||
`, {
|
||||
description: 'Try to get an old version of Filer based on git SHA, branch, or tag',
|
||||
flags: {
|
||||
out: {
|
||||
type: 'string',
|
||||
alias: 'o'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Get arg list, make sure we get a SHA argument
|
||||
cli.flags.app = cli.input.slice(1);
|
||||
if(!(cli.input && cli.input.length === 1)) {
|
||||
console.error('Specify a git SHA, branch or tag to use');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const sha = cli.input[0];
|
||||
const out = cli.flags.out || `filer-${sha}.js`;
|
||||
// https://stackoverflow.com/questions/888414/git-checkout-older-revision-of-a-file-under-a-new-name?answertab=active#tab-top
|
||||
const cmd = `git show ${sha}:dist/filer.js > ${out}`;
|
||||
spawn (cmd, [], {stdio: 'inherit', shell: true});
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
FilerWebpackPlugin: require('../src/webpack-plugin'),
|
||||
};
|
Loading…
Reference in New Issue