diff --git a/.editorconfig b/.editorconfig index e000b0ce..e7b73a7a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,4 @@ -# http://editorconfig.org +# https://editorconfig.org root = true [*] diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..404abb22 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +coverage/ diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 1482c9a2..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -github: [phated] -tidelift: npm/vinyl-fs -open_collective: gulpjs diff --git a/.github/SECURITY.md b/.github/SECURITY.md deleted file mode 100644 index 6cb3e3bd..00000000 --- a/.github/SECURITY.md +++ /dev/null @@ -1,4 +0,0 @@ -## Security contact information - -To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). -Tidelift will coordinate the fix and disclosure. diff --git a/.github/support.yml b/.github/support.yml deleted file mode 100644 index 3ee3d22c..00000000 --- a/.github/support.yml +++ /dev/null @@ -1,2 +0,0 @@ -# Configuration for support-requests - https://github.com/dessant/support-requests -_extends: gulp diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml new file mode 100644 index 00000000..d06b8760 --- /dev/null +++ b/.github/workflows/dev.yml @@ -0,0 +1,82 @@ +name: dev +on: + pull_request: + push: + branches: + - master + - main +env: + CI: true + +jobs: + prettier: + name: Format code + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' }} + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Prettier + uses: gulpjs/prettier_action@v3.0 + with: + commit_message: 'chore: Run prettier' + prettier_options: '--write .' + + test: + name: Tests for Node ${{ matrix.node }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + node: [10, 12, 14, 16] + os: [ubuntu-latest, windows-latest, macos-latest] + + steps: + - name: Clone repository + uses: actions/checkout@v2 + + - name: Set Node.js version + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node }} + + - run: node --version + - run: npm --version + + - name: Install npm dependencies + run: npm install + + - name: Run lint + run: npm run lint + + - name: Prepare files + if: ${{ !startsWith(matrix.os, 'windows') }} + run: | + find test -type d -exec chmod g+s {} \; + sudo chown root test/fixtures/not-owned/not-owned.txt + sudo chmod 666 test/fixtures/not-owned/not-owned.txt + + - name: Run tests + run: npm test + + - name: Coveralls + uses: coverallsapp/github-action@v1.1.2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + flag-name: ${{matrix.os}}-node-${{ matrix.node }} + parallel: true + + coveralls: + needs: test + name: Finish up + + runs-on: ubuntu-latest + steps: + - name: Coveralls Finished + uses: coverallsapp/github-action@v1.1.2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + parallel-finished: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..87cd13c0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,16 @@ +name: release +on: + push: + branches: + - master + - main + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - uses: GoogleCloudPlatform/release-please-action@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + release-type: node + package-name: release-please-action diff --git a/.gitignore b/.gitignore index be53f13b..3716a3bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,15 @@ # Logs logs *.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* # Runtime data pids *.pid *.seed +*.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov @@ -13,25 +17,54 @@ lib-cov # Coverage directory used by tools like istanbul coverage -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt -# Compiled binary addons (http://nodejs.org/api/addons.html) +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) build/Release -# Dependency directory -# Commenting this out is preferred by some people, see -# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- -node_modules +# Dependency directories +node_modules/ +jspm_packages/ -# Users Environment Variables -.lock-wscript +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next # Garbage files .DS_Store -# VSCode configuration files -.vscode +# Test results +test.xunit # Generated by integration tests test/out-fixtures/ diff --git a/.jscsrc b/.jscsrc deleted file mode 100644 index 703b33fc..00000000 --- a/.jscsrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "preset": "gulp" -} diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..43c97e71 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..c96ebe0c --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +coverage/ +.nyc_output/ +CHANGELOG.md diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8240af02..00000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -sudo: required -language: node_js -node_js: - - '10' - - '8' - - '6' - - '5' - - '4' - - '0.12' - - '0.10' -before_script: - - find test -type d -exec chmod g+s {} \; - - sudo chown root test/fixtures/not-owned/not-owned.txt - - sudo chmod 666 test/fixtures/not-owned/not-owned.txt -after_script: - - npm run coveralls diff --git a/LICENSE b/LICENSE index 6355a4b4..1a7d8f2b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013-2017 Blaine Bublitz , Eric Schoffstall and other contributors +Copyright (c) 2013-2020, 2023 Blaine Bublitz and Eric Schoffstall Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 8c896d81..47a85f1e 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@

- +

# vinyl-fs -[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![AppVeyor Build Status][appveyor-image]][appveyor-url] [![Coveralls Status][coveralls-image]][coveralls-url] [![Gitter chat][gitter-image]][gitter-url] +[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][ci-image]][ci-url] [![Coveralls Status][coveralls-image]][coveralls-url] [Vinyl][vinyl] adapter for the file system. @@ -18,12 +18,6 @@ While Vinyl provides a clean way to describe a file, we now need a way to access these files. Each file source needs what we call a "Vinyl adapter". A Vinyl adapter simply exposes a `src(globs)` and a `dest(folder)` method. Each return a stream. The `src` stream produces Vinyl objects, and the `dest` stream consumes Vinyl objects. Vinyl adapters can expose extra methods that might be specific to their input/output medium, such as the `symlink` method `vinyl-fs` provides. -## vinyl-fs for enterprise - -Available as part of the Tidelift Subscription - -The maintainers of vinyl-fs and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-vinyl-fs?utm_source=npm-vinyl-fs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) - ## Usage ```javascript @@ -133,7 +127,7 @@ Default: `true` Whether or not you want globs to match on dot files (e.g. `.gitignore`). -__Note: This option is not resolved from a function because it is passed verbatim to node-glob.__ +__Note: This option is not resolved from a function because it is passed verbatim to anymatch.__ Type: `Boolean` @@ -141,7 +135,7 @@ Default: `false` ##### other -Any glob-related options are documented in [glob-stream] and [node-glob] and are forwarded verbatim. +Any glob-related options are documented in [glob-stream] and [anymatch] and are forwarded verbatim. ### `dest(folder[, options])` @@ -344,28 +338,26 @@ type of link and we default to using `'file'`, which may cause unexpected behavi if you are creating a "dangling" link to a directory. It is advised to avoid this scenario. +## License -[symbolic-caveats]: #symbolic-links-on-windows -[glob-stream]: https://github.com/gulpjs/glob-stream -[node-glob]: https://github.com/isaacs/node-glob -[gaze]: https://github.com/shama/gaze -[glob-watcher]: https://github.com/wearefractal/glob-watcher -[vinyl]: https://github.com/wearefractal/vinyl -[iconv-lite]: https://github.com/ashtuchkin/iconv-lite +MIT -[downloads-image]: http://img.shields.io/npm/dm/vinyl-fs.svg + +[downloads-image]: https://img.shields.io/npm/dm/vinyl-fs.svg?style=flat-square [npm-url]: https://www.npmjs.com/package/vinyl-fs -[npm-image]: http://img.shields.io/npm/v/vinyl-fs.svg +[npm-image]: https://img.shields.io/npm/v/vinyl-fs.svg?style=flat-square -[travis-url]: https://travis-ci.org/gulpjs/vinyl-fs -[travis-image]: http://img.shields.io/travis/gulpjs/vinyl-fs.svg?label=travis-ci - -[appveyor-url]: https://ci.appveyor.com/project/gulpjs/vinyl-fs -[appveyor-image]: https://img.shields.io/appveyor/ci/gulpjs/vinyl-fs.svg?label=appveyor +[ci-url]: https://github.com/gulpjs/vinyl-fs/actions?query=workflow:dev +[ci-image]: https://img.shields.io/github/actions/workflow/status/gulpjs/vinyl-fs/dev.yml??branch=master&style=flat-square [coveralls-url]: https://coveralls.io/r/gulpjs/vinyl-fs -[coveralls-image]: http://img.shields.io/coveralls/gulpjs/vinyl-fs/master.svg - -[gitter-url]: https://gitter.im/gulpjs/gulp -[gitter-image]: https://badges.gitter.im/gulpjs/gulp.svg +[coveralls-image]: https://img.shields.io/coveralls/gulpjs/vinyl-fs.svg?style=flat-square + + +[symbolic-caveats]: #symbolic-links-on-windows +[glob-stream]: https://github.com/gulpjs/glob-stream +[anymatch]: https://github.com/micromatch/anymatch +[vinyl]: https://github.com/gulpjs/vinyl +[iconv-lite]: https://github.com/ashtuchkin/iconv-lite + diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index e416994c..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,27 +0,0 @@ -# http://www.appveyor.com/docs/appveyor-yml -# http://www.appveyor.com/docs/lang/nodejs-iojs - -environment: - matrix: - # node.js - - nodejs_version: "0.10" - - nodejs_version: "0.12" - - nodejs_version: "4" - - nodejs_version: "5" - - nodejs_version: "6" - - nodejs_version: "8" - - nodejs_version: "10" - -install: - - ps: Install-Product node $env:nodejs_version - - npm install - -test_script: - - node --version - - npm --version - - cmd: npm test - -build: off - -# build version format -version: "{build}" diff --git a/lib/codecs.js b/lib/codecs.js index ad7e93fb..e333d467 100644 --- a/lib/codecs.js +++ b/lib/codecs.js @@ -3,7 +3,9 @@ /* eslint-disable new-cap */ var iconv = require('iconv-lite'); -var through = require('through2'); +// TODO: Reaching into iconv-lite is fragile +var StripBOM = require('iconv-lite/lib/bom-handling').StripBOM; +var Transform = require('streamx').Transform; var DEFAULT_ENCODING = require('./constants').DEFAULT_ENCODING; @@ -13,78 +15,79 @@ function Codec(codec, encoding) { this.bomAware = codec.bomAware || false; } - function getEncoder(codec) { return new codec.encoder(null, codec); } -Codec.prototype.encode = function(str) { +Codec.prototype.encode = function (str) { var encoder = getEncoder(this.codec); var buf = encoder.write(str); var end = encoder.end(); return end && end.length > 0 ? Buffer.concat(buf, end) : buf; }; -Codec.prototype.encodeStream = function() { +Codec.prototype.encodeStream = function () { var encoder = getEncoder(this.codec); - return through( - { decodeStrings: false }, - function(str, enc, cb) { + return new Transform({ + transform: function (str, cb) { var buf = encoder.write(str); if (buf && buf.length) { this.push(buf); } cb(); }, - function(cb) { + flush: function (cb) { var buf = encoder.end(); if (buf && buf.length) { this.push(buf); } cb(); - } - ); + }, + }); }; - function getDecoder(codec) { return new codec.decoder(null, codec); } -Codec.prototype.decode = function(buf) { +Codec.prototype.decode = function (buf, options) { var decoder = getDecoder(this.codec); + if (options && options.removeBOM) { + decoder = new StripBOM(decoder); + } var str = decoder.write(buf); var end = decoder.end(); return end ? str + end : str; }; -Codec.prototype.decodeStream = function() { +Codec.prototype.decodeStream = function (options) { var decoder = getDecoder(this.codec); - return through( - { encoding: DEFAULT_ENCODING }, - function(buf, enc, cb) { + if (options && options.removeBOM) { + decoder = new StripBOM(decoder); + } + return new Transform({ + transform: function (buf, cb) { var str = decoder.write(buf); if (str && str.length) { - this.push(str, DEFAULT_ENCODING); + this.push(str); } cb(); }, - function(cb) { + flush: function (cb) { var str = decoder.end(); if (str && str.length) { - this.push(str, DEFAULT_ENCODING); + this.push(str); } cb(); - } - ); + }, + }); }; - var cache = {}; function getCodec(encoding) { var codec = cache[encoding]; - if (!!codec || !encoding || cache.hasOwnProperty(encoding)) { + if (!!codec || !encoding || Object.hasOwnProperty.call(cache, encoding)) { return codec; } @@ -98,7 +101,6 @@ function getCodec(encoding) { return codec; } - // Pre-load default encoding getCodec(DEFAULT_ENCODING); diff --git a/lib/dest/index.js b/lib/dest/index.js index f45dd612..a181350b 100644 --- a/lib/dest/index.js +++ b/lib/dest/index.js @@ -1,7 +1,7 @@ 'use strict'; var lead = require('lead'); -var pumpify = require('pumpify'); +var composer = require('stream-composer'); var mkdirpStream = require('fs-mkdirp-stream'); var createResolver = require('resolve-options'); @@ -31,10 +31,10 @@ function dest(outFolder, opt) { callback(null, file.dirname, dirMode); } - var saveStream = pumpify.obj( + var saveStream = composer.pipeline( prepare(folderResolver, optResolver), sourcemap(optResolver), - mkdirpStream.obj(dirpath), + mkdirpStream(dirpath), writeContents(optResolver) ); diff --git a/lib/dest/prepare.js b/lib/dest/prepare.js index b3ea3d47..1cb97611 100644 --- a/lib/dest/prepare.js +++ b/lib/dest/prepare.js @@ -4,14 +4,14 @@ var path = require('path'); var fs = require('graceful-fs'); var Vinyl = require('vinyl'); -var through = require('through2'); +var Transform = require('streamx').Transform; function prepareWrite(folderResolver, optResolver) { if (!folderResolver) { throw new Error('Invalid output folder'); } - function normalize(file, enc, cb) { + function normalize(file, cb) { if (!Vinyl.isVinyl(file)) { return cb(new Error('Received a non-Vinyl object in `dest()`')); } @@ -42,7 +42,9 @@ function prepareWrite(folderResolver, optResolver) { cb(null, file); } - return through.obj(normalize); + return new Transform({ + transform: normalize, + }); } module.exports = prepareWrite; diff --git a/lib/dest/sourcemap.js b/lib/dest/sourcemap.js index c6a89613..e10106d7 100644 --- a/lib/dest/sourcemap.js +++ b/lib/dest/sourcemap.js @@ -1,11 +1,11 @@ 'use strict'; -var through = require('through2'); +var Transform = require('streamx').Transform; var sourcemap = require('vinyl-sourcemap'); function sourcemapStream(optResolver) { - function saveSourcemap(file, enc, callback) { + function saveSourcemap(file, callback) { var self = this; var srcMap = optResolver.resolve('sourcemaps', file); @@ -32,7 +32,9 @@ function sourcemapStream(optResolver) { } } - return through.obj(saveSourcemap); + return new Transform({ + transform: saveSourcemap, + }); } module.exports = sourcemapStream; diff --git a/lib/dest/write-contents/index.js b/lib/dest/write-contents/index.js index 202a95f2..69ced5a1 100644 --- a/lib/dest/write-contents/index.js +++ b/lib/dest/write-contents/index.js @@ -1,6 +1,6 @@ 'use strict'; -var through = require('through2'); +var Transform = require('streamx').Transform; var writeDir = require('./write-dir'); var writeStream = require('./write-stream'); @@ -11,7 +11,7 @@ var fo = require('../../file-operations'); function writeContents(optResolver) { - function writeFile(file, enc, callback) { + function writeFile(file, callback) { // Write it as a symlink if (file.isSymbolic()) { return writeSymbolicLink(file, optResolver, onWritten); @@ -53,7 +53,9 @@ function writeContents(optResolver) { } - return through.obj(writeFile); + return new Transform({ + transform: writeFile, + }); } module.exports = writeContents; diff --git a/lib/dest/write-contents/write-stream.js b/lib/dest/write-contents/write-stream.js index d7c99754..84e03584 100644 --- a/lib/dest/write-contents/write-stream.js +++ b/lib/dest/write-contents/write-stream.js @@ -1,5 +1,7 @@ 'use strict'; +var pipeline = require('streamx').pipeline; + var fo = require('../../file-operations'); var getCodec = require('../../codecs'); var DEFAULT_ENCODING = require('../../constants').DEFAULT_ENCODING; @@ -26,41 +28,20 @@ function writeStream(file, optResolver, onWritten) { // TODO: is this the best API? var outStream = fo.createWriteStream(file.path, opt, onFlush); - var contents = file.contents; + // TODO: should this use a clone? + var streams = [file.contents]; if (encoding && encoding.enc !== DEFAULT_ENCODING) { - contents = contents - .pipe(getCodec(DEFAULT_ENCODING).decodeStream()) - .pipe(codec.encodeStream()); + streams.push(getCodec(DEFAULT_ENCODING).decodeStream()); + streams.push(codec.encodeStream()); } - file.contents.once('error', onComplete); - outStream.once('error', onComplete); - outStream.once('finish', onComplete); - - // TODO: should this use a clone? - contents.pipe(outStream); - - function onComplete(streamErr) { - // Cleanup event handlers before closing - file.contents.removeListener('error', onComplete); - outStream.removeListener('error', onComplete); - outStream.removeListener('finish', onComplete); + streams.push(outStream); - // Need to guarantee the fd is closed before forwarding the error - outStream.once('close', onClose); - outStream.end(); - - function onClose(closeErr) { - onWritten(streamErr || closeErr); - } - } + pipeline(streams, onWritten); // Cleanup function onFlush(fd, callback) { - // TODO: removing this before readStream because it replaces the stream - file.contents.removeListener('error', onComplete); - // TODO: this is doing sync stuff & the callback seems unnecessary readStream(file, { resolve: resolve }, complete); @@ -71,7 +52,7 @@ function writeStream(file, optResolver, onWritten) { if (key === 'removeBOM') { return false; } - throw new Error('Eek! stub resolver doesn\'t have ' + key); + throw new Error("Eek! stub resolver doesn't have " + key); } function complete() { @@ -82,7 +63,6 @@ function writeStream(file, optResolver, onWritten) { fo.updateMetadata(fd, file, callback); } } - } module.exports = writeStream; diff --git a/lib/file-operations.js b/lib/file-operations.js index b0aa31ba..27a94a7f 100644 --- a/lib/file-operations.js +++ b/lib/file-operations.js @@ -1,11 +1,8 @@ 'use strict'; -var util = require('util'); - var fs = require('graceful-fs'); -var assign = require('object.assign'); var date = require('value-or-function').date; -var Writable = require('readable-stream').Writable; +var Writable = require('streamx').Writable; var constants = require('./constants'); @@ -80,15 +77,13 @@ function getModeDiff(fsMode, vinylMode) { } function getTimesDiff(fsStat, vinylStat) { - var mtime = date(vinylStat.mtime) || 0; if (!mtime) { return; } var atime = date(vinylStat.atime) || 0; - if (+mtime === +fsStat.mtime && - +atime === +fsStat.atime) { + if (+mtime === +fsStat.mtime && +atime === +fsStat.atime) { return; } @@ -105,13 +100,14 @@ function getTimesDiff(fsStat, vinylStat) { } function getOwnerDiff(fsStat, vinylStat) { - if (!isValidUnixId(vinylStat.uid) && - !isValidUnixId(vinylStat.gid)) { + if (!isValidUnixId(vinylStat.uid) && !isValidUnixId(vinylStat.gid)) { return; } - if ((!isValidUnixId(fsStat.uid) && !isValidUnixId(vinylStat.uid)) || - (!isValidUnixId(fsStat.gid) && !isValidUnixId(vinylStat.gid))) { + if ( + (!isValidUnixId(fsStat.uid) && !isValidUnixId(vinylStat.uid)) || + (!isValidUnixId(fsStat.gid) && !isValidUnixId(vinylStat.gid)) + ) { return; } @@ -125,8 +121,7 @@ function getOwnerDiff(fsStat, vinylStat) { gid = vinylStat.gid; } - if (uid === fsStat.uid && - gid === fsStat.gid) { + if (uid === fsStat.uid && gid === fsStat.gid) { return; } @@ -139,8 +134,8 @@ function getOwnerDiff(fsStat, vinylStat) { } function isOwner(fsStat) { - var hasGetuid = (typeof process.getuid === 'function'); - var hasGeteuid = (typeof process.geteuid === 'function'); + var hasGetuid = typeof process.getuid === 'function'; + var hasGeteuid = typeof process.geteuid === 'function'; // If we don't have either, assume we don't have permissions. // This should only happen on Windows. @@ -163,6 +158,32 @@ function isOwner(fsStat) { return true; } +// Node 10 on Windows fails with EPERM if you stat a symlink to a directory so we recursively readlink before we reflect stats +// TODO: Remove this indirection when we drop Node 10 support +function findSymlinkHardpath(path, callback) { + fs.readlink(path, onReadlink); + + function onReadlink(readlinkErr, resolvedPath) { + if (readlinkErr) { + return callback(readlinkErr); + } + + fs.lstat(resolvedPath, onLstat); + + function onLstat(lstatErr, stat) { + if (lstatErr) { + return callback(lstatErr); + } + + if (stat.isSymbolicLink()) { + return findSymlinkHardpath(resolvedPath, callback); + } + + callback(null, resolvedPath); + } + } +} + function reflectStat(path, file, callback) { // Set file.stat to the reflect current state on disk fs.stat(path, onStat); @@ -192,7 +213,6 @@ function reflectLinkStat(path, file, callback) { } function updateMetadata(fd, file, callback) { - fs.fstat(fd, onStat); function onStat(statErr, stat) { @@ -210,7 +230,7 @@ function updateMetadata(fd, file, callback) { var ownerDiff = getOwnerDiff(stat, file.stat); // Set file.stat to the reflect current state on disk - assign(file.stat, stat); + Object.assign(file.stat, stat); // Nothing to do if (!modeDiff && !timesDiff && !ownerDiff) { @@ -343,140 +363,75 @@ function writeFile(filepath, data, options, callback) { } } -function createWriteStream(path, options, flush) { - return new WriteStream(path, options, flush); +function noopFlush(fd, cb) { + cb(); } -// Taken from node core and altered to receive a flush function and simplified -// To be used for cleanup (like updating times/mode/etc) -function WriteStream(path, options, flush) { - // Not exposed so we can avoid the case where someone doesn't use `new` - +function createWriteStream(path, options, flush) { if (typeof options === 'function') { flush = options; options = null; } options = options || {}; + flush = flush || noopFlush; - Writable.call(this, options); - - this.flush = flush; - this.path = path; - - this.mode = options.mode || constants.DEFAULT_FILE_MODE; - this.flags = options.flags || 'w'; - - // Used by node's `fs.WriteStream` - this.fd = null; - this.start = null; - - this.open(); - - // Dispose on finish. - this.once('finish', this.close); -} - -util.inherits(WriteStream, Writable); - -WriteStream.prototype.open = function() { - var self = this; - - fs.open(this.path, this.flags, this.mode, onOpen); - - function onOpen(openErr, fd) { - if (openErr) { - self.destroy(); - self.emit('error', openErr); - return; - } - - self.fd = fd; - self.emit('open', fd); - } -}; - -// Use our `end` method since it is patched for flush -WriteStream.prototype.destroySoon = WriteStream.prototype.end; - -WriteStream.prototype._destroy = function(err, cb) { - this.close(function(err2) { - cb(err || err2); - }); -}; - -WriteStream.prototype.close = function(cb) { - var that = this; + var mode = options.mode || constants.DEFAULT_FILE_MODE; + var flags = options.flags || 'w'; - if (cb) { - this.once('close', cb); - } + var fd = null; - if (this.closed || typeof this.fd !== 'number') { - if (typeof this.fd !== 'number') { - this.once('open', closeOnOpen); - return; - } + return new Writable({ + mapWritable: function (data) { + if (typeof data === 'string') { + return Buffer.from(data); + } else { + return data; + } + }, + open: function (cb) { + fs.open(path, flags, mode, onOpen); + + function onOpen(openErr, openedFd) { + if (openErr) { + cb(openErr); + return; + } - return process.nextTick(function() { - that.emit('close'); - }); - } + fd = openedFd; + cb(); + } + }, + destroy: function (cb) { + if (fd) { + fs.close(fd, onClose); + } else { + onClose(); + } - this.closed = true; + function onClose(closeErr) { + fd = null; + cb(closeErr); + } + }, + write: function (data, cb) { + fs.write(fd, data, 0, data.length, null, onWrite); + + function onWrite(writeErr) { + if (writeErr) { + cb(writeErr); + return; + } - fs.close(this.fd, function(er) { - if (er) { - that.emit('error', er); - } else { - that.emit('close'); - } + cb(); + } + }, + final: function (cb) { + flush(fd, cb); + }, }); - - this.fd = null; -}; - -WriteStream.prototype._final = function(callback) { - if (typeof this.flush !== 'function') { - return callback(); - } - - this.flush(this.fd, callback); -}; - -function closeOnOpen() { - this.close(); } -WriteStream.prototype._write = function(data, encoding, callback) { - var self = this; - - // This is from node core but I have no idea how to get code coverage on it - if (!Buffer.isBuffer(data)) { - return this.emit('error', new Error('Invalid data')); - } - - if (typeof this.fd !== 'number') { - return this.once('open', onOpen); - } - - fs.write(this.fd, data, 0, data.length, null, onWrite); - - function onOpen() { - self._write(data, encoding, callback); - } - - function onWrite(writeErr) { - if (writeErr) { - self.destroy(); - callback(writeErr); - return; - } - - callback(); - } -}; - module.exports = { closeFd: closeFd, isValidUnixId: isValidUnixId, @@ -487,6 +442,7 @@ module.exports = { getTimesDiff: getTimesDiff, getOwnerDiff: getOwnerDiff, isOwner: isOwner, + findSymlinkHardpath: findSymlinkHardpath, reflectStat: reflectStat, reflectLinkStat: reflectLinkStat, updateMetadata: updateMetadata, diff --git a/lib/src/index.js b/lib/src/index.js index 6f531cea..99d2cda6 100644 --- a/lib/src/index.js +++ b/lib/src/index.js @@ -1,9 +1,10 @@ 'use strict'; var gs = require('glob-stream'); -var pumpify = require('pumpify'); +var pipeline = require('streamx').pipeline; var toThrough = require('to-through'); var isValidGlob = require('is-valid-glob'); +var normalizePath = require('normalize-path'); var createResolver = require('resolve-options'); var config = require('./options'); @@ -20,19 +21,18 @@ function src(glob, opt) { throw new Error('Invalid glob argument: ' + glob); } - var streams = [ + glob = normalizePath(glob, false); + + var outputStream = pipeline( gs(glob, opt), wrapVinyl(optResolver), resolveSymlinks(optResolver), prepare(optResolver), readContents(optResolver), - sourcemap(optResolver), - ]; - - var outputStream = pumpify.obj(streams); + sourcemap(optResolver) + ); return toThrough(outputStream); } - module.exports = src; diff --git a/lib/src/prepare.js b/lib/src/prepare.js index 5fa18dff..3dbd5524 100644 --- a/lib/src/prepare.js +++ b/lib/src/prepare.js @@ -1,10 +1,10 @@ 'use strict'; -var through = require('through2'); +var Transform = require('streamx').Transform; function prepareRead(optResolver) { - function normalize(file, enc, callback) { + function normalize(file, callback) { var since = optResolver.resolve('since', file); @@ -16,7 +16,9 @@ function prepareRead(optResolver) { return callback(null, file); } - return through.obj(normalize); + return new Transform({ + transform: normalize, + }); } module.exports = prepareRead; diff --git a/lib/src/read-contents/index.js b/lib/src/read-contents/index.js index 105e0ed2..f09360cc 100644 --- a/lib/src/read-contents/index.js +++ b/lib/src/read-contents/index.js @@ -1,6 +1,6 @@ 'use strict'; -var through = require('through2'); +var Transform = require('streamx').Transform; var readDir = require('./read-dir'); var readStream = require('./read-stream'); @@ -9,7 +9,7 @@ var readSymbolicLink = require('./read-symbolic-link'); function readContents(optResolver) { - function readFile(file, enc, callback) { + function readFile(file, callback) { // Skip reading contents if read option says so var read = optResolver.resolve('read', file); @@ -46,7 +46,9 @@ function readContents(optResolver) { } } - return through.obj(readFile); + return new Transform({ + transform: readFile, + }); } module.exports = readContents; diff --git a/lib/src/read-contents/read-buffer.js b/lib/src/read-contents/read-buffer.js index a38b9ce1..28f9863f 100644 --- a/lib/src/read-contents/read-buffer.js +++ b/lib/src/read-contents/read-buffer.js @@ -1,7 +1,6 @@ 'use strict'; var fs = require('graceful-fs'); -var removeBomBuffer = require('remove-bom-buffer'); var getCodec = require('../../codecs'); var DEFAULT_ENCODING = require('../../constants').DEFAULT_ENCODING; @@ -23,15 +22,10 @@ function bufferFile(file, optResolver, onRead) { if (encoding) { var removeBOM = codec.bomAware && optResolver.resolve('removeBOM', file); - if (codec.enc !== DEFAULT_ENCODING) { - contents = codec.decode(contents); - removeBOM = removeBOM && contents[0] === '\ufeff'; + if (removeBOM || codec.enc !== DEFAULT_ENCODING) { + contents = codec.decode(contents, { removeBOM: removeBOM }); contents = getCodec(DEFAULT_ENCODING).encode(contents); } - - if (removeBOM) { - contents = removeBomBuffer(contents); - } } file.contents = contents; diff --git a/lib/src/read-contents/read-stream.js b/lib/src/read-contents/read-stream.js index 108e8738..b0d0d781 100644 --- a/lib/src/read-contents/read-stream.js +++ b/lib/src/read-contents/read-stream.js @@ -1,7 +1,7 @@ 'use strict'; var fs = require('graceful-fs'); -var removeBomStream = require('remove-bom-stream'); +var composer = require('stream-composer'); var lazystream = require('lazystream'); var getCodec = require('../../codecs'); @@ -16,24 +16,25 @@ function streamFile(file, optResolver, onRead) { var filePath = file.path; - file.contents = new lazystream.Readable(function() { + file.contents = new lazystream.Readable(function () { var contents = fs.createReadStream(filePath); + var streams = [contents]; + if (encoding) { var removeBOM = codec.bomAware && optResolver.resolve('removeBOM', file); - if (codec.enc !== DEFAULT_ENCODING) { - contents = contents - .pipe(codec.decodeStream()) - .pipe(getCodec(DEFAULT_ENCODING).encodeStream()); - } - - if (removeBOM) { - contents = contents.pipe(removeBomStream()); + if (removeBOM || codec.enc !== DEFAULT_ENCODING) { + streams.push(codec.decodeStream({ removeBOM: removeBOM })); + streams.push(getCodec(DEFAULT_ENCODING).encodeStream()); } } - return contents; + if (streams.length > 1) { + return composer.pipeline(streams); + } else { + return contents; + } }); onRead(); diff --git a/lib/src/resolve-symlinks.js b/lib/src/resolve-symlinks.js index d77f912f..945831cb 100644 --- a/lib/src/resolve-symlinks.js +++ b/lib/src/resolve-symlinks.js @@ -1,12 +1,12 @@ 'use strict'; -var through = require('through2'); +var Transform = require('streamx').Transform; var fo = require('../file-operations'); function resolveSymlinks(optResolver) { // A stat property is exposed on file objects as a (wanted) side effect - function resolveFile(file, enc, callback) { + function resolveFile(file, callback) { fo.reflectLinkStat(file.path, file, onReflect); @@ -25,12 +25,22 @@ function resolveSymlinks(optResolver) { return callback(null, file); } + fo.findSymlinkHardpath(file.path, onSymlinkHardpath); + } + + function onSymlinkHardpath(readlinkErr, path) { + if (readlinkErr) { + return callback(readlinkErr); + } + // Get target's stats - fo.reflectStat(file.path, file, onReflect); + fo.reflectStat(path, file, onReflect); } } - return through.obj(resolveFile); + return new Transform({ + transform: resolveFile, + }); } module.exports = resolveSymlinks; diff --git a/lib/src/sourcemap.js b/lib/src/sourcemap.js index e03971f1..651dc49b 100644 --- a/lib/src/sourcemap.js +++ b/lib/src/sourcemap.js @@ -1,11 +1,11 @@ 'use strict'; -var through = require('through2'); +var Transform = require('streamx').Transform; var sourcemap = require('vinyl-sourcemap'); function sourcemapStream(optResolver) { - function addSourcemap(file, enc, callback) { + function addSourcemap(file, callback) { var srcMap = optResolver.resolve('sourcemaps', file); if (!srcMap) { @@ -23,7 +23,9 @@ function sourcemapStream(optResolver) { } } - return through.obj(addSourcemap); + return new Transform({ + transform: addSourcemap, + }); } module.exports = sourcemapStream; diff --git a/lib/src/wrap-vinyl.js b/lib/src/wrap-vinyl.js index 883c5575..605bd1c2 100644 --- a/lib/src/wrap-vinyl.js +++ b/lib/src/wrap-vinyl.js @@ -1,18 +1,20 @@ 'use strict'; var File = require('vinyl'); -var through = require('through2'); +var Transform = require('streamx').Transform; function wrapVinyl() { - function wrapFile(globFile, enc, callback) { + function wrapFile(globFile, callback) { var file = new File(globFile); callback(null, file); } - return through.obj(wrapFile); + return new Transform({ + transform: wrapFile, + }); } module.exports = wrapVinyl; diff --git a/lib/symlink/index.js b/lib/symlink/index.js index 6e835da0..a9a006dd 100644 --- a/lib/symlink/index.js +++ b/lib/symlink/index.js @@ -1,7 +1,7 @@ 'use strict'; -var pumpify = require('pumpify'); var lead = require('lead'); +var composer = require('stream-composer'); var mkdirpStream = require('fs-mkdirp-stream'); var createResolver = require('resolve-options'); @@ -30,9 +30,9 @@ function symlink(outFolder, opt) { callback(null, file.dirname, dirMode); } - var stream = pumpify.obj( + var stream = composer.pipeline( prepare(folderResolver, optResolver), - mkdirpStream.obj(dirpath), + mkdirpStream(dirpath), linkFile(optResolver) ); diff --git a/lib/symlink/link-file.js b/lib/symlink/link-file.js index e1caf977..ecebe182 100644 --- a/lib/symlink/link-file.js +++ b/lib/symlink/link-file.js @@ -3,7 +3,7 @@ var os = require('os'); var path = require('path'); -var through = require('through2'); +var Transform = require('streamx').Transform; var fo = require('../file-operations'); @@ -11,7 +11,7 @@ var isWindows = (os.platform() === 'win32'); function linkStream(optResolver) { - function linkFile(file, enc, callback) { + function linkFile(file, callback) { var isRelative = optResolver.resolve('relativeSymlinks', file); var flags = fo.getFlags({ overwrite: optResolver.resolve('overwrite', file), @@ -83,7 +83,9 @@ function linkStream(optResolver) { } } - return through.obj(linkFile); + return new Transform({ + transform: linkFile, + }); } module.exports = linkStream; diff --git a/lib/symlink/prepare.js b/lib/symlink/prepare.js index dd2ec1ad..49f0b2e3 100644 --- a/lib/symlink/prepare.js +++ b/lib/symlink/prepare.js @@ -4,14 +4,14 @@ var path = require('path'); var fs = require('graceful-fs'); var Vinyl = require('vinyl'); -var through = require('through2'); +var Transform = require('streamx').Transform; function prepareSymlink(folderResolver, optResolver) { if (!folderResolver) { throw new Error('Invalid output folder'); } - function normalize(file, enc, cb) { + function normalize(file, cb) { if (!Vinyl.isVinyl(file)) { return cb(new Error('Received a non-Vinyl object in `symlink()`')); } @@ -45,7 +45,9 @@ function prepareSymlink(folderResolver, optResolver) { cb(null, file); } - return through.obj(normalize); + return new Transform({ + transform: normalize, + }); } module.exports = prepareSymlink; diff --git a/package.json b/package.json index ffaa3ba1..ea9dada4 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vinyl-fs", "version": "3.0.3", "description": "Vinyl adapter for the file system.", - "author": "Gulp Team (http://gulpjs.com/)", + "author": "Gulp Team (https://gulpjs.com/)", "contributors": [ "Eric Schoffstall ", "Blaine Bublitz " @@ -10,7 +10,7 @@ "repository": "gulpjs/vinyl-fs", "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=10.13.0" }, "main": "index.js", "files": [ @@ -19,43 +19,45 @@ "lib" ], "scripts": { - "lint": "eslint . && jscs index.js lib/ test/", + "lint": "eslint .", "pretest": "npm run lint", - "test": "mocha --async-only", - "cover": "istanbul cover _mocha --report lcovonly", - "coveralls": "npm run cover && istanbul-coveralls" + "test": "nyc mocha --async-only" }, "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "iconv-lite": "^0.4.24", + "fs-mkdirp-stream": "^2.0.1", + "glob-stream": "^8.0.0", + "graceful-fs": "^4.2.11", + "iconv-lite": "^0.6.3", "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" + "lazystream": "^1.0.1", + "lead": "^4.0.0", + "normalize-path": "3.0.0", + "resolve-options": "^2.0.0", + "stream-composer": "^1.0.2", + "streamx": "^2.14.0", + "to-through": "^3.0.0", + "value-or-function": "^4.0.0", + "vinyl": "^3.0.0", + "vinyl-sourcemap": "^2.0.0" }, "devDependencies": { - "eslint": "^1.10.3", - "eslint-config-gulp": "^2.0.0", - "expect": "^1.19.0", - "istanbul": "^0.4.3", - "istanbul-coveralls": "^1.0.3", - "jscs": "^2.4.0", - "jscs-preset-gulp": "^1.0.0", - "mississippi": "^1.2.0", - "mocha": "^3.5.0", - "rimraf": "^2.6.1" + "eslint": "^7.32.0", + "eslint-config-gulp": "^5.0.1", + "expect": "^27.5.1", + "mocha": "^8.4.0", + "nyc": "^15.1.0", + "readable-stream": "3.6.0", + "rimraf": "^3.0.2", + "sinon": "^15.0.2" + }, + "nyc": { + "reporter": [ + "lcov", + "text-summary" + ] + }, + "prettier": { + "singleQuote": true }, "keywords": [ "gulp", diff --git a/test/.eslintrc b/test/.eslintrc deleted file mode 100644 index 06b940f7..00000000 --- a/test/.eslintrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "gulp/test" -} diff --git a/test/.gitkeep b/test/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/codecs.js b/test/codecs.js index 0222e05a..3be967fe 100644 --- a/test/codecs.js +++ b/test/codecs.js @@ -2,17 +2,14 @@ var fs = require('graceful-fs'); var expect = require('expect'); -var miss = require('mississippi'); - -var from = miss.from; -var pipe = miss.pipe; -var concat = miss.concat; var getCodec = require('../lib/codecs'); var DEFAULT_ENCODING = require('../lib/constants').DEFAULT_ENCODING; var testCodec = require('./utils/codecs'); +var testStreams = require('./utils/test-streams'); var testConstants = require('./utils/test-constants'); +var describeStreams = require('./utils/suite'); var beNotBomInputPath = testConstants.beNotBomInputPath; var leNotBomInputPath = testConstants.leNotBomInputPath; @@ -20,208 +17,233 @@ var notBomContents = testConstants.notBomContents; var encodedInputPath = testConstants.encodedInputPath; var encodedContents = testConstants.encodedContents; -describe('codecs', function() { - - it('exports a function', function(done) { +describe('codecs', function () { + it('exports a function', function (done) { expect(typeof getCodec).toEqual('function'); done(); }); - it('returns undefined for unsupported encoding', function(done) { + it('returns undefined for unsupported encoding', function (done) { var codec = getCodec('fubar42'); expect(codec).toBe(undefined); done(); }); - it('returns a proper codec for default encoding ' + DEFAULT_ENCODING, function(done) { - var codec = getCodec(DEFAULT_ENCODING); + it( + 'returns a proper codec for default encoding ' + DEFAULT_ENCODING, + function (done) { + var codec = getCodec(DEFAULT_ENCODING); + testCodec(codec); + expect(codec.enc).toEqual(DEFAULT_ENCODING); + expect(codec.bomAware).toEqual(true); + done(); + } + ); + + it('returns a proper codec for utf16be', function (done) { + var codec = getCodec('utf16be'); testCodec(codec); - expect(codec.enc).toEqual(DEFAULT_ENCODING); - expect(codec.bomAware).toBe(true); + expect(codec.bomAware).toEqual(true); done(); }); - it('returns a proper codec for utf16be', function(done) { - var codec = getCodec('utf16be'); + it('returns a proper codec for utf16le', function (done) { + var codec = getCodec('utf16le'); testCodec(codec); - expect(codec.bomAware).toBe(true); + expect(codec.bomAware).toEqual(true); done(); }); - it('can decode bytes from utf16be encoding to a string (buffer)', function(done) { - var codec = getCodec('utf16be'); - var expected = notBomContents.replace('X', 'BE'); - - var result = codec.decode(fs.readFileSync(beNotBomInputPath)); - expect(result).toExist(); - expect(typeof result).toEqual('string'); - expect(result.slice(2)).toEqual(expected); // Ignore leading garbage + it('returns a proper codec for gb2312', function (done) { + var codec = getCodec('gb2312'); + testCodec(codec); done(); }); - it('can decode bytes from utf16be encoding to a string (stream)', function(done) { - var codec = getCodec('utf16be'); - var expected = notBomContents.replace('X', 'BE'); + describe('buffer', function () { + it('can decode bytes from utf16be encoding to a string', function (done) { + var codec = getCodec('utf16be'); + var expected = notBomContents.replace('X', 'BE'); - function assert(result) { - expect(result).toExist(); + var result = codec.decode(fs.readFileSync(beNotBomInputPath)); + expect(result).toEqual(expect.anything()); expect(typeof result).toEqual('string'); expect(result.slice(2)).toEqual(expected); // Ignore leading garbage - } + done(); + }); - pipe([ - fs.createReadStream(beNotBomInputPath), - codec.decodeStream(), - concat(assert), - ], done); - }); + it('can encode a string to bytes in utf16be encoding', function (done) { + var codec = getCodec('utf16be'); + var expected = fs.readFileSync(beNotBomInputPath); - it('can encode a string to bytes in utf16be encoding (buffer)', function(done) { - var codec = getCodec('utf16be'); - var expected = fs.readFileSync(beNotBomInputPath); - - var result = codec.encode(notBomContents.replace('X', 'BE')); - expect(result).toExist(); - expect(typeof result).toEqual('object'); - expect(Buffer.isBuffer(result)).toBe(true); - expect(result).toMatch(expected.slice(4)); // Ignore leading garbage - done(); - }); - - it('can encode a string to bytes in utf16be encoding (stream)', function(done) { - var codec = getCodec('utf16be'); - var expected = fs.readFileSync(beNotBomInputPath); - - function assert(result) { - expect(result).toExist(); + var result = codec.encode(notBomContents.replace('X', 'BE')); + expect(result).toEqual(expect.anything()); expect(typeof result).toEqual('object'); expect(Buffer.isBuffer(result)).toBe(true); - expect(result).toMatch(expected.slice(4)); // Ignore leading garbage - } + expect(result).toEqual(expected.slice(4)); // Ignore leading garbage + done(); + }); - pipe([ - from.obj([notBomContents.replace('X', 'BE')]), - codec.encodeStream(), - concat(assert), - ], done); - }); - - it('returns a proper codec for utf16le', function(done) { - var codec = getCodec('utf16le'); - testCodec(codec); - expect(codec.bomAware).toBe(true); - done(); - }); - - it('can decode bytes from utf16le encoding to a string (buffer)', function(done) { - var codec = getCodec('utf16le'); - var expected = notBomContents.replace('X', 'LE'); - - var result = codec.decode(fs.readFileSync(leNotBomInputPath)); - expect(result).toExist(); - expect(typeof result).toEqual('string'); - expect(result.slice(2)).toEqual(expected); // Ignore leading garbage - done(); - }); - - it('can decode bytes from utf16le encoding to a string (stream)', function(done) { - var codec = getCodec('utf16le'); - var expected = notBomContents.replace('X', 'LE'); + it('can decode bytes from utf16le encoding to a string', function (done) { + var codec = getCodec('utf16le'); + var expected = notBomContents.replace('X', 'LE'); - function assert(result) { - expect(result).toExist(); + var result = codec.decode(fs.readFileSync(leNotBomInputPath)); + expect(result).toEqual(expect.anything()); expect(typeof result).toEqual('string'); expect(result.slice(2)).toEqual(expected); // Ignore leading garbage - } - - pipe([ - fs.createReadStream(leNotBomInputPath), - codec.decodeStream(), - concat(assert), - ], done); - }); - - it('can encode a string to bytes in utf16le encoding (buffer)', function(done) { - var codec = getCodec('utf16le'); - var expected = fs.readFileSync(leNotBomInputPath); + done(); + }); - var result = codec.encode(notBomContents.replace('X', 'LE')); - expect(result).toExist(); - expect(typeof result).toEqual('object'); - expect(Buffer.isBuffer(result)).toBe(true); - expect(result).toMatch(expected.slice(4)); // Ignore leading garbage - done(); - }); - - it('can encode a string to bytes in utf16le encoding (stream)', function(done) { - var codec = getCodec('utf16le'); - var expected = fs.readFileSync(leNotBomInputPath); + it('can encode a string to bytes in utf16le encoding', function (done) { + var codec = getCodec('utf16le'); + var expected = fs.readFileSync(leNotBomInputPath); - function assert(result) { - expect(result).toExist(); + var result = codec.encode(notBomContents.replace('X', 'LE')); + expect(result).toEqual(expect.anything()); expect(typeof result).toEqual('object'); expect(Buffer.isBuffer(result)).toBe(true); - expect(result).toMatch(expected.slice(4)); // Ignore leading garbage - } - - pipe([ - from.obj([notBomContents.replace('X', 'LE')]), - codec.encodeStream(), - concat(assert), - ], done); - }); + expect(result).toEqual(expected.slice(4)); // Ignore leading garbage + done(); + }); - it('returns a proper codec for gb2312', function(done) { - var codec = getCodec('gb2312'); - testCodec(codec); - done(); - }); - - it('can decode bytes from gb2312 encoding to a string (buffer)', function(done) { - var codec = getCodec('gb2312'); - var expected = encodedContents; + it('can decode bytes from gb2312 encoding to a string', function (done) { + var codec = getCodec('gb2312'); + var expected = encodedContents; - var result = codec.decode(fs.readFileSync(encodedInputPath)); - expect(result).toEqual(expected); - done(); - }); - - it('can decode bytes from gb2312 encoding to a string (stream)', function(done) { - var codec = getCodec('gb2312'); - var expected = encodedContents; - - function assert(result) { + var result = codec.decode(fs.readFileSync(encodedInputPath)); expect(result).toEqual(expected); - } - - pipe([ - fs.createReadStream(encodedInputPath), - codec.decodeStream(), - concat(assert), - ], done); - }); + done(); + }); - it('can encode a string to bytes in gb2312 encoding (buffer)', function(done) { - var codec = getCodec('gb2312'); - var expected = fs.readFileSync(encodedInputPath); + it('can encode a string to bytes in gb2312 encoding', function (done) { + var codec = getCodec('gb2312'); + var expected = fs.readFileSync(encodedInputPath); - var result = codec.encode(encodedContents); - expect(result).toMatch(expected); - done(); - }); - - it('can encode a string to bytes in gb2312 encoding (stream)', function(done) { - var codec = getCodec('gb2312'); - var expected = fs.readFileSync(encodedInputPath); - - function assert(result) { - expect(result).toMatch(expected); - } - - pipe([ - from.obj([encodedContents]), - codec.encodeStream(), - concat(assert), - ], done); + var result = codec.encode(encodedContents); + expect(result).toEqual(expected); + done(); + }); + }); + + describeStreams('stream', function (stream) { + var from = stream.Readable.from; + var pipeline = stream.pipeline; + + var streamUtils = testStreams(stream); + var concatString = streamUtils.concatString; + var concatBuffer = streamUtils.concatBuffer; + + it('can decode bytes from utf16be encoding to a string', function (done) { + var codec = getCodec('utf16be'); + var expected = notBomContents.replace('X', 'BE'); + + function assert(result) { + expect(result).toEqual(expect.anything()); + expect(typeof result).toEqual('string'); + expect(result.slice(2)).toEqual(expected); // Ignore leading garbage + } + + pipeline( + [ + fs.createReadStream(beNotBomInputPath), + codec.decodeStream(), + concatString(assert), + ], + done + ); + }); + + it('can encode a string to bytes in utf16be encoding', function (done) { + var codec = getCodec('utf16be'); + var expected = fs.readFileSync(beNotBomInputPath); + + function assert(result) { + expect(result).toEqual(expect.anything()); + expect(Buffer.isBuffer(result)).toBe(true); + expect(result).toEqual(expected.slice(4)); // Ignore leading garbage + } + + pipeline( + [ + from([notBomContents.replace('X', 'BE')]), + codec.encodeStream(), + concatBuffer(assert), + ], + done + ); + }); + + it('can decode bytes from utf16le encoding to a string', function (done) { + var codec = getCodec('utf16le'); + var expected = notBomContents.replace('X', 'LE'); + + function assert(result) { + expect(result).toEqual(expect.anything()); + expect(typeof result).toEqual('string'); + expect(result.slice(2)).toEqual(expected); // Ignore leading garbage + } + + pipeline( + [ + fs.createReadStream(leNotBomInputPath), + codec.decodeStream(), + concatString(assert), + ], + done + ); + }); + + it('can encode a string to bytes in utf16le encoding', function (done) { + var codec = getCodec('utf16le'); + var expected = fs.readFileSync(leNotBomInputPath); + + function assert(result) { + expect(result).toEqual(expect.anything()); + expect(Buffer.isBuffer(result)).toBe(true); + expect(result).toEqual(expected.slice(4)); // Ignore leading garbage + } + + pipeline( + [ + from([notBomContents.replace('X', 'LE')]), + codec.encodeStream(), + concatBuffer(assert), + ], + done + ); + }); + + it('can decode bytes from gb2312 encoding to a string', function (done) { + var codec = getCodec('gb2312'); + var expected = encodedContents; + + function assert(result) { + expect(result).toEqual(expected); + } + + pipeline( + [ + fs.createReadStream(encodedInputPath), + codec.decodeStream(), + concatString(assert), + ], + done + ); + }); + + it('can encode a string to bytes in gb2312 encoding', function (done) { + var codec = getCodec('gb2312'); + var expected = fs.readFileSync(encodedInputPath); + + function assert(result) { + expect(result).toEqual(expected); + } + + pipeline( + [from([encodedContents]), codec.encodeStream(), concatBuffer(assert)], + done + ); + }); }); }); diff --git a/test/dest-modes.js b/test/dest-modes.js index 5f315a0e..3c6bca42 100644 --- a/test/dest-modes.js +++ b/test/dest-modes.js @@ -3,7 +3,7 @@ var fs = require('graceful-fs'); var File = require('vinyl'); var expect = require('expect'); -var miss = require('mississippi'); +var sinon = require('sinon'); var vfs = require('../'); @@ -14,10 +14,7 @@ var isWindows = require('./utils/is-windows'); var applyUmask = require('./utils/apply-umask'); var always = require('./utils/always'); var testConstants = require('./utils/test-constants'); - -var from = miss.from; -var pipe = miss.pipe; -var concat = miss.concat; +var describeStreams = require('./utils/suite'); var inputBase = testConstants.inputBase; var outputBase = testConstants.outputBase; @@ -31,12 +28,14 @@ var contents = testConstants.contents; var clean = cleanup(outputBase); -describe('.dest() with custom modes', function() { +describeStreams('.dest() with custom modes', function (stream) { + var from = stream.Readable.from; + var pipeline = stream.pipeline; beforeEach(clean); afterEach(clean); - it('sets the mode of a written buffer file if set on the vinyl object', function(done) { + it('sets the mode of a written buffer file if set on the vinyl object', function (done) { // Changing the mode of a file is not supported by node.js in Windows. // Windows is treated as though it does not have permission to make this operation. if (isWindows) { @@ -49,7 +48,7 @@ describe('.dest() with custom modes', function() { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { mode: expectedMode, }, @@ -57,16 +56,13 @@ describe('.dest() with custom modes', function() { function assert() { expect(statMode(outputPath)).toEqual(expectedMode); + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('sets the sticky bit on the mode of a written stream file if set on the vinyl object', function(done) { + it('sets the sticky bit on the mode of a written stream file if set on the vinyl object', function (done) { if (isWindows) { this.skip(); return; @@ -85,16 +81,13 @@ describe('.dest() with custom modes', function() { function assert() { expect(statMode(outputPath)).toEqual(expectedMode); + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('sets the mode of a written stream file if set on the vinyl object', function(done) { + it('sets the mode of a written stream file if set on the vinyl object', function (done) { if (isWindows) { this.skip(); return; @@ -113,16 +106,13 @@ describe('.dest() with custom modes', function() { function assert() { expect(statMode(outputPath)).toEqual(expectedMode); + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('sets the mode of a written directory if set on the vinyl object', function(done) { + it('sets the mode of a written directory if set on the vinyl object', function (done) { if (isWindows) { this.skip(); return; @@ -142,16 +132,13 @@ describe('.dest() with custom modes', function() { function assert() { expect(statMode(outputDirpath)).toEqual(expectedMode); + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('sets sticky bit on the mode of a written directory if set on the vinyl object', function(done) { + it('sets sticky bit on the mode of a written directory if set on the vinyl object', function (done) { if (isWindows) { this.skip(); return; @@ -171,16 +158,13 @@ describe('.dest() with custom modes', function() { function assert() { expect(statMode(outputDirpath)).toEqual(expectedMode); + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('writes new files with the mode specified in options', function(done) { + it('writes new files with the mode specified in options', function (done) { if (isWindows) { this.skip(); return; @@ -191,21 +175,24 @@ describe('.dest() with custom modes', function() { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert() { expect(statMode(outputPath)).toEqual(expectedMode); + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname, mode: expectedMode }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { cwd: __dirname, mode: expectedMode }), + ], + assert + ); }); - it('updates the file mode to match the vinyl mode', function(done) { + it('updates the file mode to match the vinyl mode', function (done) { if (isWindows) { this.skip(); return; @@ -217,7 +204,7 @@ describe('.dest() with custom modes', function() { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { mode: expectedMode, }, @@ -225,20 +212,17 @@ describe('.dest() with custom modes', function() { function assert() { expect(statMode(outputPath)).toEqual(expectedMode); + done(); } fs.mkdirSync(outputBase); fs.closeSync(fs.openSync(outputPath, 'w')); fs.chmodSync(outputPath, startMode); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('updates the directory mode to match the vinyl mode', function(done) { + it('updates the directory mode to match the vinyl mode', function (done) { if (isWindows) { this.skip(); return; @@ -266,16 +250,16 @@ describe('.dest() with custom modes', function() { function assert() { expect(statMode(outputDirpath)).toEqual(expectedMode); + done(); } - pipe([ - from.obj([file1, file2]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline( + [from([file1, file2]), vfs.dest(outputBase, { cwd: __dirname })], + assert + ); }); - it('uses different modes for files and directories', function(done) { + it('uses different modes for files and directories', function (done) { if (isWindows) { this.skip(); return; @@ -287,63 +271,63 @@ describe('.dest() with custom modes', function() { var file = new File({ base: inputBase, path: inputNestedPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert() { expect(statMode(outputDirpath)).toEqual(expectedDirMode); expect(statMode(outputNestedPath)).toEqual(expectedFileMode); + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { - cwd: __dirname, - mode: expectedFileMode, - dirMode: expectedDirMode, - }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { + cwd: __dirname, + mode: expectedFileMode, + dirMode: expectedDirMode, + }), + ], + assert + ); }); - it('does not fchmod a matching file', function(done) { + it('does not fchmod a matching file', function (done) { if (isWindows) { this.skip(); return; } - var fchmodSpy = expect.spyOn(fs, 'fchmod').andCallThrough(); + var fchmodSpy = sinon.spy(fs, 'fchmod'); var expectedMode = applyUmask('777'); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { mode: expectedMode, }, }); function assert() { - expect(fchmodSpy.calls.length).toEqual(0); + expect(fchmodSpy.callCount).toEqual(0); expect(statMode(outputPath)).toEqual(expectedMode); + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('sees a file with special chmod (setuid/setgid/sticky) as distinct', function(done) { + it('sees a file with special chmod (setuid/setgid/sticky) as distinct', function (done) { if (isWindows) { this.skip(); return; } - var fchmodSpy = expect.spyOn(fs, 'fchmod').andCallThrough(); + var fchmodSpy = sinon.spy(fs, 'fchmod'); var startMode = applyUmask('3722'); var expectedMode = applyUmask('722'); @@ -351,28 +335,25 @@ describe('.dest() with custom modes', function() { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { mode: expectedMode, }, }); function assert() { - expect(fchmodSpy.calls.length).toEqual(1); + expect(fchmodSpy.callCount).toEqual(1); + done(); } fs.mkdirSync(outputBase); fs.closeSync(fs.openSync(outputPath, 'w')); fs.chmodSync(outputPath, startMode); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('reports fchmod errors', function(done) { + it('reports fchmod errors', function (done) { if (isWindows) { this.skip(); return; @@ -380,29 +361,26 @@ describe('.dest() with custom modes', function() { var expectedMode = applyUmask('722'); - var fchmodSpy = expect.spyOn(fs, 'fchmod').andCall(mockError); + var fchmodSpy = sinon.stub(fs, 'fchmod').callsFake(mockError); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { mode: expectedMode, }, }); function assert(err) { - expect(err).toExist(); - expect(fchmodSpy.calls.length).toEqual(1); + expect(err).toEqual(expect.anything()); + expect(fchmodSpy.callCount).toEqual(1); done(); } fs.mkdirSync(outputBase); fs.closeSync(fs.openSync(outputPath, 'w')); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - ], assert); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); }); diff --git a/test/dest-owner.js b/test/dest-owner.js index b6701e59..6b852344 100644 --- a/test/dest-owner.js +++ b/test/dest-owner.js @@ -3,17 +3,14 @@ var fs = require('graceful-fs'); var File = require('vinyl'); var expect = require('expect'); -var miss = require('mississippi'); +var sinon = require('sinon'); var vfs = require('../'); var cleanup = require('./utils/cleanup'); var isWindows = require('./utils/is-windows'); var testConstants = require('./utils/test-constants'); - -var from = miss.from; -var pipe = miss.pipe; -var concat = miss.concat; +var describeStreams = require('./utils/suite'); var inputBase = testConstants.inputBase; var outputBase = testConstants.outputBase; @@ -22,23 +19,25 @@ var contents = testConstants.contents; var clean = cleanup(outputBase); -describe('.dest() with custom owner', function() { +describeStreams('.dest() with custom owner', function (stream) { + var from = stream.Readable.from; + var pipeline = stream.pipeline; beforeEach(clean); afterEach(clean); - it('calls fchown when the uid and/or gid are provided on the vinyl stat', function(done) { + it('calls fchown when the uid and/or gid are provided on the vinyl stat', function (done) { if (isWindows) { this.skip(); return; } - var fchownSpy = expect.spyOn(fs, 'fchown').andCallThrough(); + var fchownSpy = sinon.spy(fs, 'fchown'); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { uid: 1001, gid: 1001, @@ -46,30 +45,27 @@ describe('.dest() with custom owner', function() { }); function assert() { - expect(fchownSpy.calls.length).toEqual(1); - expect(fchownSpy.calls[0].arguments[1]).toEqual(1001); - expect(fchownSpy.calls[0].arguments[2]).toEqual(1001); + expect(fchownSpy.callCount).toEqual(1); + expect(fchownSpy.getCall(0).args[1]).toEqual(1001); + expect(fchownSpy.getCall(0).args[2]).toEqual(1001); + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase)], assert); }); - it('does not call fchown when the uid and gid provided on the vinyl stat are invalid', function(done) { + it('does not call fchown when the uid and gid provided on the vinyl stat are invalid', function (done) { if (isWindows) { this.skip(); return; } - var fchownSpy = expect.spyOn(fs, 'fchown').andCallThrough(); + var fchownSpy = sinon.spy(fs, 'fchown'); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { uid: -1, gid: -1, @@ -77,13 +73,10 @@ describe('.dest() with custom owner', function() { }); function assert() { - expect(fchownSpy.calls.length).toEqual(0); + expect(fchownSpy.callCount).toEqual(0); + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase)], assert); }); }); diff --git a/test/dest-symlinks.js b/test/dest-symlinks.js index b1ba7ea9..9a6d7143 100644 --- a/test/dest-symlinks.js +++ b/test/dest-symlinks.js @@ -5,18 +5,15 @@ var path = require('path'); var fs = require('graceful-fs'); var File = require('vinyl'); var expect = require('expect'); -var miss = require('mississippi'); var vfs = require('../'); var cleanup = require('./utils/cleanup'); var isWindows = require('./utils/is-windows'); var always = require('./utils/always'); +var testStreams = require('./utils/test-streams'); var testConstants = require('./utils/test-constants'); - -var from = miss.from; -var pipe = miss.pipe; -var concat = miss.concat; +var describeStreams = require('./utils/suite'); var inputBase = testConstants.inputBase; var outputBase = testConstants.outputBase; @@ -33,12 +30,17 @@ var neOutputDirpath = testConstants.neOutputDirpath; var clean = cleanup(outputBase); -describe('.dest() with symlinks', function() { +describeStreams('.dest() with symlinks', function (stream) { + var from = stream.Readable.from; + var pipeline = stream.pipeline; + + var streamUtils = testStreams(stream); + var concatArray = streamUtils.concatArray; beforeEach(clean); afterEach(clean); - it('creates symlinks when `file.isSymbolic()` is true', function(done) { + it('creates symlinks when `file.isSymbolic()` is true', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -61,14 +63,10 @@ describe('.dest() with symlinks', function() { expect(files[0].path).toEqual(outputPath); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('does not create symlinks when `file.isSymbolic()` is false', function(done) { + it('does not create symlinks when `file.isSymbolic()` is false', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -88,14 +86,10 @@ describe('.dest() with symlinks', function() { expect(symlinkExists).toBe(false); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('errors if missing a `.symlink` property', function(done) { + it('errors if missing a `.symlink` property', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -106,18 +100,15 @@ describe('.dest() with symlinks', function() { }); function assert(err) { - expect(err).toExist(); + expect(err).toEqual(expect.anything()); expect(err.message).toEqual('Missing symlink property on symbolic vinyl'); done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - ], assert); + pipeline([from([file]), vfs.dest(outputBase)], assert); }); - it('emits Vinyl files that are (still) symbolic', function(done) { + it('emits Vinyl files that are (still) symbolic', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -135,14 +126,10 @@ describe('.dest() with symlinks', function() { expect(files[0].isSymbolic()).toEqual(true); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('can create relative links', function(done) { + it('can create relative links', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -163,14 +150,17 @@ describe('.dest() with symlinks', function() { expect(files[0].isSymbolic()).toBe(true); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { relativeSymlinks: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { relativeSymlinks: true }), + concatArray(assert), + ], + done + ); }); - it('(*nix) creates a link for a directory', function(done) { + it('(*nix) creates a link for a directory', function (done) { if (isWindows) { this.skip(); return; @@ -199,14 +189,10 @@ describe('.dest() with symlinks', function() { expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('(windows) creates a junction for a directory', function(done) { + it('(windows) creates a junction for a directory', function (done) { if (!isWindows) { this.skip(); return; @@ -236,14 +222,10 @@ describe('.dest() with symlinks', function() { expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('(windows) options can disable junctions for a directory', function(done) { + it('(windows) options can disable junctions for a directory', function (done) { if (!isWindows) { this.skip(); return; @@ -272,14 +254,17 @@ describe('.dest() with symlinks', function() { expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { useJunctions: false }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { useJunctions: false }), + concatArray(assert), + ], + done + ); }); - it('(windows) options can disable junctions for a directory (as a function)', function(done) { + it('(windows) options can disable junctions for a directory (as a function)', function (done) { if (!isWindows) { this.skip(); return; @@ -298,7 +283,7 @@ describe('.dest() with symlinks', function() { file.symlink = inputDirpath; function useJunctions(f) { - expect(f).toExist(); + expect(f).toEqual(expect.anything()); expect(f).toBe(file); return false; } @@ -314,14 +299,17 @@ describe('.dest() with symlinks', function() { expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { useJunctions: useJunctions }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { useJunctions: useJunctions }), + concatArray(assert), + ], + done + ); }); - it('(*nix) can create relative links for directories', function(done) { + it('(*nix) can create relative links for directories', function (done) { if (isWindows) { this.skip(); return; @@ -350,14 +338,17 @@ describe('.dest() with symlinks', function() { expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { relativeSymlinks: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { relativeSymlinks: true }), + concatArray(assert), + ], + done + ); }); - it('(*nix) receives a virtual symbolic directory and creates a symlink', function(done) { + it('(*nix) receives a virtual symbolic directory and creates a symlink', function (done) { if (isWindows) { this.skip(); return; @@ -386,18 +377,21 @@ describe('.dest() with symlinks', function() { expect(lstats.isSymbolicLink()).toEqual(true); } - pipe([ - // This could also be from a different Vinyl adapter - from.obj([file]), - vfs.dest(neOutputBase), - concat(assert), - ], done); + pipeline( + [ + // This could also be from a different Vinyl adapter + from([file]), + vfs.dest(neOutputBase), + concatArray(assert), + ], + done + ); }); // There's no way to determine the proper type of link to create with a dangling link // So we just create a 'file' type symlink // There's also no real way to test the type that was created - it('(windows) receives a virtual symbolic directory and creates a symlink', function(done) { + it('(windows) receives a virtual symbolic directory and creates a symlink', function (done) { if (!isWindows) { this.skip(); return; @@ -426,15 +420,18 @@ describe('.dest() with symlinks', function() { expect(lstats.isSymbolicLink()).toEqual(true); } - pipe([ - // This could also be from a different Vinyl adapter - from.obj([file]), - vfs.dest(neOutputBase), - concat(assert), - ], done); + pipeline( + [ + // This could also be from a different Vinyl adapter + from([file]), + vfs.dest(neOutputBase), + concatArray(assert), + ], + done + ); }); - it('(windows) relativeSymlinks option is ignored when junctions are used', function(done) { + it('(windows) relativeSymlinks option is ignored when junctions are used', function (done) { if (!isWindows) { this.skip(); return; @@ -464,14 +461,20 @@ describe('.dest() with symlinks', function() { expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { useJunctions: true, relativeSymlinks: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { + useJunctions: true, + relativeSymlinks: true, + }), + concatArray(assert), + ], + done + ); }); - it('(windows) supports relativeSymlinks option when link is not for a directory', function(done) { + it('(windows) supports relativeSymlinks option when link is not for a directory', function (done) { if (!isWindows) { this.skip(); return; @@ -496,15 +499,21 @@ describe('.dest() with symlinks', function() { expect(outputLink).toEqual(path.normalize('../fixtures/test.txt')); } - pipe([ - from.obj([file]), - // The useJunctions option is ignored when file is not a directory - vfs.dest(outputBase, { useJunctions: true, relativeSymlinks: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + // The useJunctions option is ignored when file is not a directory + vfs.dest(outputBase, { + useJunctions: true, + relativeSymlinks: true, + }), + concatArray(assert), + ], + done + ); }); - it('(windows) can create relative links for directories when junctions are disabled', function(done) { + it('(windows) can create relative links for directories when junctions are disabled', function (done) { if (!isWindows) { this.skip(); return; @@ -528,7 +537,7 @@ describe('.dest() with symlinks', function() { var outputLink = fs.readlinkSync(outputDirpath); expect(files.length).toEqual(1); - expect(files).toInclude(file); + expect(files).toContain(file); expect(files[0].base).toEqual(outputBase, 'base should have changed'); expect(files[0].path).toEqual(outputDirpath, 'path should have changed'); expect(outputLink).toEqual(path.normalize('../fixtures/foo')); @@ -536,14 +545,20 @@ describe('.dest() with symlinks', function() { expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { useJunctions: false, relativeSymlinks: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { + useJunctions: false, + relativeSymlinks: true, + }), + concatArray(assert), + ], + done + ); }); - it('does not overwrite links with overwrite option set to false', function(done) { + it('does not overwrite links with overwrite option set to false', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ @@ -569,15 +584,17 @@ describe('.dest() with symlinks', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { overwrite: false }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { overwrite: false }), + concatArray(assert), + ], + done + ); }); - - it('overwrites links with overwrite option set to true', function(done) { + it('overwrites links with overwrite option set to true', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ @@ -603,14 +620,17 @@ describe('.dest() with symlinks', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { overwrite: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { overwrite: true }), + concatArray(assert), + ], + done + ); }); - it('does not overwrite links with overwrite option set to a function that returns false', function(done) { + it('does not overwrite links with overwrite option set to a function that returns false', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ @@ -641,14 +661,17 @@ describe('.dest() with symlinks', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { overwrite: overwrite }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { overwrite: overwrite }), + concatArray(assert), + ], + done + ); }); - it('overwrites links with overwrite option set to a function that returns true', function(done) { + it('overwrites links with overwrite option set to a function that returns true', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ @@ -679,10 +702,13 @@ describe('.dest() with symlinks', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { overwrite: overwrite }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { overwrite: overwrite }), + concatArray(assert), + ], + done + ); }); }); diff --git a/test/dest-times.js b/test/dest-times.js index 97cefd61..18699239 100644 --- a/test/dest-times.js +++ b/test/dest-times.js @@ -3,17 +3,14 @@ var fs = require('graceful-fs'); var File = require('vinyl'); var expect = require('expect'); -var miss = require('mississippi'); +var sinon = require('sinon'); var vfs = require('../'); var cleanup = require('./utils/cleanup'); var isWindows = require('./utils/is-windows'); var testConstants = require('./utils/test-constants'); - -var from = miss.from; -var pipe = miss.pipe; -var concat = miss.concat; +var describeStreams = require('./utils/suite'); var inputBase = testConstants.inputBase; var outputBase = testConstants.outputBase; @@ -23,12 +20,14 @@ var contents = testConstants.contents; var clean = cleanup(outputBase); -describe('.dest() with custom times', function() { +describeStreams('.dest() with custom times', function (stream) { + var from = stream.Readable.from; + var pipeline = stream.pipeline; beforeEach(clean); afterEach(clean); - it('does not call futimes when no mtime is provided on the vinyl stat', function(done) { + it('does not call futimes when no mtime is provided on the vinyl stat', function (done) { // Changing the time of a directory errors in Windows. // Windows is treated as though it does not have permission to make this operation. if (isWindows) { @@ -38,31 +37,28 @@ describe('.dest() with custom times', function() { var earlier = Date.now() - 1001; - var futimesSpy = expect.spyOn(fs, 'futimes').andCallThrough(); + var futimesSpy = sinon.spy(fs, 'futimes'); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: {}, }); function assert() { var stats = fs.lstatSync(outputPath); - expect(futimesSpy.calls.length).toEqual(0); + expect(futimesSpy.callCount).toEqual(0); expect(stats.atime.getTime()).toBeGreaterThan(earlier); expect(stats.mtime.getTime()).toBeGreaterThan(earlier); + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('calls futimes when an mtime is provided on the vinyl stat', function(done) { + it('calls futimes when an mtime is provided on the vinyl stat', function (done) { if (isWindows) { this.skip(); return; @@ -71,37 +67,34 @@ describe('.dest() with custom times', function() { // Use new mtime var mtime = new Date(Date.now() - 2048); - var futimesSpy = expect.spyOn(fs, 'futimes').andCallThrough(); + var futimesSpy = sinon.spy(fs, 'futimes'); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { mtime: mtime, }, }); function assert() { - expect(futimesSpy.calls.length).toEqual(1); + expect(futimesSpy.callCount).toEqual(1); // Compare args instead of fs.lstats(), since mtime may be drifted in x86 Node.js - var mtimeSpy = futimesSpy.calls[0].arguments[2]; + var mtimeSpy = futimesSpy.getCall(0).args[2]; - expect(mtimeSpy.getTime()) - .toEqual(mtime.getTime()); + expect(mtimeSpy.getTime()).toEqual(mtime.getTime()); expect(file.stat.mtime).toEqual(mtime); + + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('does not call futimes when provided mtime on the vinyl stat is invalid', function(done) { + it('does not call futimes when provided mtime on the vinyl stat is invalid', function (done) { if (isWindows) { this.skip(); return; @@ -109,12 +102,12 @@ describe('.dest() with custom times', function() { var earlier = Date.now() - 1001; - var futimesSpy = expect.spyOn(fs, 'futimes').andCallThrough(); + var futimesSpy = sinon.spy(fs, 'futimes'); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { mtime: new Date(undefined), }, @@ -123,18 +116,16 @@ describe('.dest() with custom times', function() { function assert() { var stats = fs.lstatSync(outputPath); - expect(futimesSpy.calls.length).toEqual(0); + expect(futimesSpy.callCount).toEqual(0); expect(stats.mtime.getTime()).toBeGreaterThan(earlier); + + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('calls futimes when provided mtime on the vinyl stat is valid but provided atime is invalid', function(done) { + it('calls futimes when provided mtime on the vinyl stat is valid but provided atime is invalid', function (done) { if (isWindows) { this.skip(); return; @@ -144,12 +135,12 @@ describe('.dest() with custom times', function() { var mtime = new Date(Date.now() - 2048); var invalidAtime = new Date(undefined); - var futimesSpy = expect.spyOn(fs, 'futimes').andCallThrough(); + var futimesSpy = sinon.spy(fs, 'futimes'); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { atime: invalidAtime, mtime: mtime, @@ -157,21 +148,19 @@ describe('.dest() with custom times', function() { }); function assert() { - expect(futimesSpy.calls.length).toEqual(1); + expect(futimesSpy.callCount).toEqual(1); - var mtimeSpy = futimesSpy.calls[0].arguments[2]; + var mtimeSpy = futimesSpy.getCall(0).args[2]; expect(mtimeSpy.getTime()).toEqual(mtime.getTime()); + + done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); - it('writes file atime and mtime using the vinyl stat', function(done) { + it('writes file atime and mtime using the vinyl stat', function (done) { if (isWindows) { this.skip(); return; @@ -181,12 +170,12 @@ describe('.dest() with custom times', function() { var atime = new Date(Date.now() - 2048); var mtime = new Date(Date.now() - 1024); - var futimesSpy = expect.spyOn(fs, 'futimes').andCallThrough(); + var futimesSpy = sinon.spy(fs, 'futimes'); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { atime: atime, mtime: mtime, @@ -194,21 +183,19 @@ describe('.dest() with custom times', function() { }); function assert() { - expect(futimesSpy.calls.length).toEqual(1); + expect(futimesSpy.callCount).toEqual(1); - var atimeSpy = futimesSpy.calls[0].arguments[1]; - var mtimeSpy = futimesSpy.calls[0].arguments[2]; + var atimeSpy = futimesSpy.getCall(0).args[1]; + var mtimeSpy = futimesSpy.getCall(0).args[2]; expect(atimeSpy.getTime()).toEqual(atime.getTime()); expect(mtimeSpy.getTime()).toEqual(mtime.getTime()); expect(file.stat.mtime).toEqual(mtime); expect(file.stat.atime).toEqual(atime); - }; - pipe([ - from.obj([file]), - vfs.dest(outputBase, { cwd: __dirname }), - concat(assert), - ], done); + done(); + } + + pipeline([from([file]), vfs.dest(outputBase, { cwd: __dirname })], assert); }); }); diff --git a/test/dest.js b/test/dest.js index 5adf0a8f..713b684b 100644 --- a/test/dest.js +++ b/test/dest.js @@ -5,7 +5,7 @@ var path = require('path'); var fs = require('graceful-fs'); var File = require('vinyl'); var expect = require('expect'); -var miss = require('mississippi'); +var sinon = require('sinon'); var vfs = require('../'); @@ -17,17 +17,7 @@ var testStreams = require('./utils/test-streams'); var always = require('./utils/always'); var testConstants = require('./utils/test-constants'); var breakPrototype = require('./utils/break-prototype'); - -var from = miss.from; -var pipe = miss.pipe; -var concat = miss.concat; -var through = miss.through; - -var count = testStreams.count; -var rename = testStreams.rename; -var includes = testStreams.includes; -var slowCount = testStreams.slowCount; -var string = testStreams.string; +var describeStreams = require('./utils/suite'); function noop() {} @@ -60,113 +50,148 @@ function makeSourceMap() { var clean = cleanup(outputBase); -describe('.dest()', function() { +describeStreams('.dest()', function (stream) { + var from = stream.Readable.from; + var pipeline = stream.pipeline; + + var streamUtils = testStreams(stream); + + var count = streamUtils.count; + var rename = streamUtils.rename; + var includes = streamUtils.includes; + var slowCount = streamUtils.slowCount; + var chunks = streamUtils.chunks; + var concatArray = streamUtils.concatArray; + var compareContents = streamUtils.compareContents; + var fromError = streamUtils.fromError; beforeEach(clean); afterEach(clean); - it('throws on no folder argument', function(done) { + it('throws on no folder argument', function (done) { function noFolder() { vfs.dest(); } - expect(noFolder).toThrow('Invalid dest() folder argument. Please specify a non-empty string or a function.'); + expect(noFolder).toThrow( + 'Invalid dest() folder argument. Please specify a non-empty string or a function.' + ); done(); }); - it('throws on empty string folder argument', function(done) { + it('throws on empty string folder argument', function (done) { function emptyFolder() { vfs.dest(''); } - expect(emptyFolder).toThrow('Invalid dest() folder argument. Please specify a non-empty string or a function.'); + expect(emptyFolder).toThrow( + 'Invalid dest() folder argument. Please specify a non-empty string or a function.' + ); done(); }); - it('accepts the sourcemap option as true', function(done) { + it('accepts the sourcemap option as true', function (done) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), sourceMap: makeSourceMap(), }); function assert(files) { expect(files.length).toEqual(1); - expect(files).toInclude(file); + expect(files).toContain(file); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { sourcemaps: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { sourcemaps: true }), + concatArray(assert), + ], + done + ); }); - it('accepts the sourcemap option as a string', function(done) { + it('accepts the sourcemap option as a string', function (done) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), sourceMap: makeSourceMap(), }); function assert(files) { expect(files.length).toEqual(2); - expect(files).toInclude(file); + expect(files).toContain(file); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { sourcemaps: '.' }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { sourcemaps: '.' }), + concatArray(assert), + ], + done + ); }); - it('inlines sourcemaps when option is true', function(done) { + it('inlines sourcemaps when option is true', function (done) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), sourceMap: makeSourceMap(), }); function assert(files) { expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].contents.toString()).toMatch(new RegExp(sourcemapContents)); + expect(files).toContain(file); + expect(files[0].contents.toString()).toMatch( + new RegExp(sourcemapContents) + ); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { sourcemaps: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { sourcemaps: true }), + concatArray(assert), + ], + done + ); }); - it('generates an extra File when option is a string', function(done) { + it('generates an extra File when option is a string', function (done) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), sourceMap: makeSourceMap(), }); function assert(files) { expect(files.length).toEqual(2); - expect(files).toInclude(file); - expect(files[0].contents.toString()).toMatch(new RegExp('//# sourceMappingURL=test.txt.map')); - expect(files[1].contents).toEqual(JSON.stringify(makeSourceMap())); + expect(files).toContain(file); + expect(files[0].contents.toString()).toMatch( + new RegExp('//# sourceMappingURL=test.txt.map') + ); + expect(files[1].contents.toString()).toEqual( + JSON.stringify(makeSourceMap()) + ); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { sourcemaps: '.' }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { sourcemaps: '.' }), + concatArray(assert), + ], + done + ); }); - it('passes through writes with cwd', function(done) { + it('passes through writes with cwd', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -175,18 +200,21 @@ describe('.dest()', function() { function assert(files) { expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].cwd).toEqual(__dirname, 'cwd should have changed'); + expect(files).toContain(file); + expect(files[0].cwd).toEqual(__dirname); } - pipe([ - from.obj([file]), - vfs.dest(outputRelative, { cwd: __dirname }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputRelative, { cwd: __dirname }), + concatArray(assert), + ], + done + ); }); - it('passes through writes with default cwd', function(done) { + it('passes through writes with default cwd', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -195,18 +223,14 @@ describe('.dest()', function() { function assert(files) { expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].cwd).toEqual(process.cwd(), 'cwd should not have changed'); + expect(files).toContain(file); + expect(files[0].cwd).toEqual(process.cwd()); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('does not write null files', function(done) { + it('does not write null files', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -217,58 +241,57 @@ describe('.dest()', function() { var exists = fs.existsSync(outputPath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputPath, 'path should have changed'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputPath); expect(exists).toEqual(false); - }; + } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('writes buffer files to the right folder with relative cwd', function(done) { + it('writes buffer files to the right folder with relative cwd', function (done) { var cwd = path.relative(process.cwd(), __dirname); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert(files) { var outputContents = fs.readFileSync(outputPath, 'utf8'); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].cwd).toEqual(__dirname, 'cwd should have changed'); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputPath, 'path should have changed'); + expect(files).toContain(file); + expect(files[0].cwd).toEqual(__dirname); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputPath); expect(outputContents).toEqual(contents); } - pipe([ - from.obj([file]), - vfs.dest(outputRelative, { cwd: cwd }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputRelative, { cwd: cwd }), + concatArray(assert), + ], + done + ); }); - it('writes buffer files to the right folder with function and relative cwd', function(done) { + it('writes buffer files to the right folder with function and relative cwd', function (done) { var cwd = path.relative(process.cwd(), __dirname); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function outputFn(f) { - expect(f).toExist(); - expect(f).toExist(file); + expect(f).toEqual(expect.anything()); + expect(f).toEqual(file); return outputRelative; } @@ -276,45 +299,40 @@ describe('.dest()', function() { var outputContents = fs.readFileSync(outputPath, 'utf8'); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].cwd).toEqual(__dirname, 'cwd should have changed'); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputPath, 'path should have changed'); + expect(files).toContain(file); + expect(files[0].cwd).toEqual(__dirname); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputPath); expect(outputContents).toEqual(contents); } - pipe([ - from.obj([file]), - vfs.dest(outputFn, { cwd: cwd }), - concat(assert), - ], done); + pipeline( + [from([file]), vfs.dest(outputFn, { cwd: cwd }), concatArray(assert)], + done + ); }); - it('writes buffer files to the right folder', function(done) { + it('writes buffer files to the right folder', function (done) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert(files) { var outputContents = fs.readFileSync(outputPath, 'utf8'); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputPath, 'path should have changed'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputPath); expect(outputContents).toEqual(contents); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('writes streaming files to the right folder', function(done) { + it('writes streaming files to the right folder', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -325,44 +343,38 @@ describe('.dest()', function() { var outputContents = fs.readFileSync(outputPath, 'utf8'); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputPath, 'path should have changed'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputPath); expect(outputContents).toEqual(contents); - }; + } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('writes large streaming files to the right folder', function(done) { + it('writes large streaming files to the right folder', function (done) { + this.timeout(0); + var size = 40000; var file = new File({ base: inputBase, path: inputPath, - contents: string(size), + contents: chunks(size), }); function assert(files) { var stats = fs.lstatSync(outputPath); expect(files.length).toEqual(1); - expect(files).toInclude(file); + expect(files).toContain(file); expect(stats.size).toEqual(size); - }; + } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('writes directories to the right folder', function(done) { + it('writes directories to the right folder', function (done) { var file = new File({ base: inputBase, path: inputDirpath, @@ -376,25 +388,21 @@ describe('.dest()', function() { var stats = fs.lstatSync(outputDirpath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); // TODO: normalize this path - expect(files[0].path).toEqual(outputDirpath, 'path should have changed'); + expect(files[0].path).toEqual(outputDirpath); expect(stats.isDirectory()).toEqual(true); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('allows piping multiple dests in streaming mode', function(done) { + it('allows piping multiple dests in streaming mode', function (done) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert() { @@ -404,48 +412,47 @@ describe('.dest()', function() { expect(outputContents2).toEqual(contents); } - pipe([ - from.obj([file]), - includes({ path: inputPath }), - vfs.dest(outputBase), - rename(outputRenamePath), - includes({ path: outputRenamePath }), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline( + [ + from([file]), + includes({ path: inputPath }), + vfs.dest(outputBase), + rename(outputRenamePath), + includes({ path: outputRenamePath }), + vfs.dest(outputBase), + concatArray(assert), + ], + done + ); }); - it('writes new files with the default user mode', function(done) { + it('writes new files with the default user mode', function (done) { var expectedMode = applyUmask('666'); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert(files) { expect(files.length).toEqual(1); - expect(files).toInclude(file); + expect(files).toContain(file); expect(statMode(outputPath)).toEqual(expectedMode); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('reports i/o errors', function(done) { + it('reports i/o errors', function (done) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert(err) { - expect(err).toExist(); + expect(err).toEqual(expect.anything()); done(); } @@ -453,48 +460,42 @@ describe('.dest()', function() { fs.closeSync(fs.openSync(outputPath, 'w')); fs.chmodSync(outputPath, 0); - pipe([ - from.obj([file]), - vfs.dest(outputBase), - ], assert); + pipeline([from([file]), vfs.dest(outputBase)], assert); }); - it('reports stat errors', function(done) { + it('reports stat errors', function (done) { var expectedMode = applyUmask('722'); - var fstatSpy = expect.spyOn(fs, 'fstat').andCall(mockError); + var fstatSpy = sinon.stub(fs, 'fstat').callsFake(mockError); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { mode: expectedMode, }, }); function assert(err) { - expect(err).toExist(); - expect(fstatSpy.calls.length).toEqual(1); + expect(err).toEqual(expect.anything()); + expect(fstatSpy.callCount).toEqual(1); done(); } fs.mkdirSync(outputBase); fs.closeSync(fs.openSync(outputPath, 'w')); - pipe([ - from.obj([file]), - vfs.dest(outputBase), - ], assert); + pipeline([from([file]), vfs.dest(outputBase)], assert); }); - it('does not overwrite files with overwrite option set to false', function(done) { + it('does not overwrite files with overwrite option set to false', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert(files) { @@ -508,20 +509,23 @@ describe('.dest()', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { overwrite: false }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { overwrite: false }), + concatArray(assert), + ], + done + ); }); - it('overwrites files with overwrite option set to true', function(done) { + it('overwrites files with overwrite option set to true', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert(files) { @@ -535,20 +539,23 @@ describe('.dest()', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { overwrite: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { overwrite: true }), + concatArray(assert), + ], + done + ); }); - it('does not overwrite files with overwrite option set to a function that returns false', function(done) { + it('does not overwrite files with overwrite option set to a function that returns false', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function overwrite(f) { @@ -567,20 +574,23 @@ describe('.dest()', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { overwrite: overwrite }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { overwrite: overwrite }), + concatArray(assert), + ], + done + ); }); - it('overwrites files with overwrite option set to a function that returns true', function(done) { + it('overwrites files with overwrite option set to a function that returns true', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function overwrite(f) { @@ -599,20 +609,23 @@ describe('.dest()', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { overwrite: overwrite }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { overwrite: overwrite }), + concatArray(assert), + ], + done + ); }); - it('appends content with append option set to true', function(done) { + it('appends content with append option set to true', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert(files) { @@ -626,20 +639,23 @@ describe('.dest()', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { append: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { append: true }), + concatArray(assert), + ], + done + ); }); - it('appends content with append option set to a function that returns true', function(done) { + it('appends content with append option set to a function that returns true', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function append(f) { @@ -658,14 +674,17 @@ describe('.dest()', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.dest(outputBase, { append: append }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { append: append }), + concatArray(assert), + ], + done + ); }); - it('does not do any transcoding with encoding option set to false (buffer)', function(done) { + it('does not do any transcoding with encoding option set to false (buffer)', function (done) { var expectedContents = fs.readFileSync(ranBomInputPath); var file = new File({ base: inputBase, @@ -677,17 +696,20 @@ describe('.dest()', function() { var outputContents = fs.readFileSync(outputPath); expect(files.length).toEqual(1); - expect(outputContents).toMatch(expectedContents); + expect(outputContents).toEqual(expectedContents); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { encoding: false }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { encoding: false }), + concatArray(assert), + ], + done + ); }); - it('does not do any transcoding with encoding option set to false (stream)', function(done) { + it('does not do any transcoding with encoding option set to false (stream)', function (done) { var expectedContents = fs.readFileSync(ranBomInputPath); var file = new File({ base: inputBase, @@ -699,39 +721,45 @@ describe('.dest()', function() { var outputContents = fs.readFileSync(outputPath); expect(files.length).toEqual(1); - expect(outputContents).toMatch(expectedContents); + expect(outputContents).toEqual(expectedContents); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { encoding: false }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { encoding: false }), + concatArray(assert), + ], + done + ); }); - it('transcodes utf8 to gb2312 with encoding option (buffer)', function(done) { + it('transcodes utf8 to gb2312 with encoding option (buffer)', function (done) { var expectedContents = fs.readFileSync(encodedInputPath); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(encodedContents), + contents: Buffer.from(encodedContents), }); function assert(files) { var outputContents = fs.readFileSync(outputPath); expect(files.length).toEqual(1); - expect(outputContents).toMatch(expectedContents); + expect(outputContents).toEqual(expectedContents); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { encoding: 'gb2312' }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { encoding: 'gb2312' }), + concatArray(assert), + ], + done + ); }); - it('transcodes utf8 to gb2312 with encoding option (stream)', function(done) { + it('transcodes utf8 to gb2312 with encoding option (stream)', function (done) { var expectedContents = fs.readFileSync(encodedInputPath); var file = new File({ base: inputBase, @@ -743,19 +771,22 @@ describe('.dest()', function() { var outputContents = fs.readFileSync(outputPath); expect(files.length).toEqual(1); - expect(outputContents).toMatch(expectedContents); + expect(outputContents).toEqual(expectedContents); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { encoding: 'gb2312' }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { encoding: 'gb2312' }), + concatArray(assert), + ], + done + ); }); - it('sends utf8 downstream despite encoding option, preserve BOM if any (buffer)', function(done) { + it('sends utf8 downstream despite encoding option, preserve BOM if any (buffer)', function (done) { var expectedString = '\ufeff' + bomContents.replace('X', '16-BE'); - var expectedContents = new Buffer(expectedString); + var expectedContents = Buffer.from(expectedString); var file = new File({ base: inputBase, @@ -766,19 +797,22 @@ describe('.dest()', function() { function assert(files) { expect(files.length).toEqual(1); expect(files[0].isBuffer()).toEqual(true); - expect(files[0].contents).toMatch(expectedContents); + expect(files[0].contents).toEqual(expectedContents); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { encoding: 'utf16be' }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { encoding: 'utf16be' }), + concatArray(assert), + ], + done + ); }); - it('sends utf8 downstream despite encoding option, preserve BOM if any (stream)', function(done) { + it('sends utf8 downstream despite encoding option, preserve BOM if any (stream)', function (done) { var expectedString = '\ufeff' + bomContents.replace('X', '16-BE'); - var expectedContents = new Buffer(expectedString); + var expectedContents = Buffer.from(expectedString); var file = new File({ base: inputBase, @@ -787,35 +821,30 @@ describe('.dest()', function() { }); function assertContent(contents) { - expect(contents).toMatch(expectedContents); + expect(contents).toEqual(expectedContents); } - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); - } function assert(files) { expect(files.length).toEqual(1); expect(files[0].isStream()).toEqual(true); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { encoding: 'utf16be' }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { encoding: 'utf16be' }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); - it('reports unsupported encoding errors (buffer)', function(done) { + it('reports unsupported encoding errors (buffer)', function (done) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert(files) { @@ -823,19 +852,22 @@ describe('.dest()', function() { } function finish(err) { - expect(err).toExist(); + expect(err).toEqual(expect.anything()); expect(err.message).toEqual('Unsupported encoding: fubar42'); done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { encoding: 'fubar42' }), - concat(assert), - ], finish); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { encoding: 'fubar42' }), + concatArray(assert), + ], + finish + ); }); - it('reports unsupported encoding errors (stream)', function(done) { + it('reports unsupported encoding errors (stream)', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -847,58 +879,69 @@ describe('.dest()', function() { } function finish(err) { - expect(err).toExist(); + expect(err).toEqual(expect.anything()); expect(err.message).toEqual('Unsupported encoding: fubar42'); done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { encoding: 'fubar42' }), - concat(assert), - ], finish); + pipeline( + [ + from([file]), + vfs.dest(outputBase, { encoding: 'fubar42' }), + concatArray(assert), + ], + finish + ); }); - it('emits a finish event', function(done) { + it('emits a finish event', function (done) { var destStream = vfs.dest(outputBase); - destStream.once('finish', done); + var finished = false; + destStream.once('finish', function () { + finished = true; + }); var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer('1234567890'), + contents: Buffer.from('1234567890'), }); - pipe([ - from.obj([file]), - destStream, - ]); + function finish() { + expect(finished).toBeTruthy(); + done(); + } + + pipeline([from([file]), destStream], finish); }); - it('does not get clogged by highWaterMark', function(done) { + it('does not get clogged by highWaterMark', function (done) { var expectedCount = 17; var highwatermarkFiles = []; for (var idx = 0; idx < expectedCount; idx++) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); highwatermarkFiles.push(file); } - pipe([ - from.obj(highwatermarkFiles), - count(expectedCount), - // Must be in the Writable position to test this - // So concat-stream cannot be used - vfs.dest(outputBase), - ], done); + pipeline( + [ + from(highwatermarkFiles), + count(expectedCount), + // Must be in the Writable position to test this + // So concat-stream cannot be used + vfs.dest(outputBase), + ], + done + ); }); - it('allows backpressure when piped to another, slower stream', function(done) { - this.timeout(20000); + it('allows backpressure when piped to another, slower stream', function (done) { + this.timeout(0); var expectedCount = 24; var highwatermarkFiles = []; @@ -906,20 +949,23 @@ describe('.dest()', function() { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); highwatermarkFiles.push(file); } - pipe([ - from.obj(highwatermarkFiles), - count(expectedCount), - vfs.dest(outputBase), - slowCount(expectedCount), - ], done); + pipeline( + [ + from(highwatermarkFiles), + count(expectedCount), + vfs.dest(outputBase), + slowCount(expectedCount), + ], + done + ); }); - it('respects readable listeners on destination stream', function(done) { + it('respects readable listeners on destination stream', function (done) { var file = new File({ base: inputBase, path: inputDirpath, @@ -929,7 +975,7 @@ describe('.dest()', function() { var destStream = vfs.dest(outputBase); var readables = 0; - destStream.on('readable', function() { + destStream.on('readable', function () { var data = destStream.read(); if (data != null) { @@ -942,13 +988,10 @@ describe('.dest()', function() { done(err); } - pipe([ - from.obj([file]), - destStream, - ], assert); + pipeline([from([file]), destStream], assert); }); - it('respects data listeners on destination stream', function(done) { + it('respects data listeners on destination stream', function (done) { var file = new File({ base: inputBase, path: inputDirpath, @@ -958,7 +1001,7 @@ describe('.dest()', function() { var destStream = vfs.dest(outputBase); var datas = 0; - destStream.on('data', function() { + destStream.on('data', function () { datas++; }); @@ -967,20 +1010,17 @@ describe('.dest()', function() { done(err); } - pipe([ - from.obj([file]), - destStream, - ], assert); + pipeline([from([file]), destStream], assert); }); - it('sinks the stream if all the readable event handlers are removed', function(done) { + it('sinks the stream if all the readable event handlers are removed', function (done) { var expectedCount = 17; var highwatermarkFiles = []; for (var idx = 0; idx < expectedCount; idx++) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); highwatermarkFiles.push(file); } @@ -989,27 +1029,30 @@ describe('.dest()', function() { destStream.on('readable', noop); - pipe([ - from.obj(highwatermarkFiles), - count(expectedCount), - // Must be in the Writable position to test this - // So concat-stream cannot be used - destStream, - ], done); - - process.nextTick(function() { + pipeline( + [ + from(highwatermarkFiles), + count(expectedCount), + // Must be in the Writable position to test this + // So concat-stream cannot be used + destStream, + ], + done + ); + + process.nextTick(function () { destStream.removeListener('readable', noop); }); }); - it('sinks the stream if all the data event handlers are removed', function(done) { + it('sinks the stream if all the data event handlers are removed', function (done) { var expectedCount = 17; var highwatermarkFiles = []; for (var idx = 0; idx < expectedCount; idx++) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); highwatermarkFiles.push(file); } @@ -1018,64 +1061,58 @@ describe('.dest()', function() { destStream.on('data', noop); - pipe([ - from.obj(highwatermarkFiles), - count(expectedCount), - // Must be in the Writable position to test this - // So concat-stream cannot be used - destStream, - ], done); - - process.nextTick(function() { + pipeline( + [ + from(highwatermarkFiles), + count(expectedCount), + // Must be in the Writable position to test this + // So concat-stream cannot be used + destStream, + ], + done + ); + + process.nextTick(function () { destStream.removeListener('data', noop); }); }); - it('successfully processes files with streaming contents', function(done) { + it('successfully processes files with streaming contents', function (done) { var file = new File({ base: inputBase, path: inputPath, contents: from([contents]), }); - pipe([ - from.obj([file]), - vfs.dest(outputBase), - ], done); + pipeline([from([file]), vfs.dest(outputBase)], done); }); - it('errors when a non-Vinyl object is emitted', function(done) { + it('errors when a non-Vinyl object is emitted', function (done) { var file = {}; function assert(err) { - expect(err).toExist(); + expect(err).toEqual(expect.anything()); expect(err.message).toEqual('Received a non-Vinyl object in `dest()`'); done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - ], assert); + pipeline([from([file]), vfs.dest(outputBase)], assert); }); - it('errors when a buffer-mode stream is piped to it', function(done) { - var file = new Buffer('test'); + it('errors when a buffer-mode stream is piped to it', function (done) { + var file = Buffer.from('test'); function assert(err) { - expect(err).toExist(); + expect(err).toEqual(expect.anything()); expect(err.message).toEqual('Received a non-Vinyl object in `dest()`'); done(); } - pipe([ - from([file]), - vfs.dest(outputBase), - ], assert); + pipeline([from([file]), vfs.dest(outputBase)], assert); }); - it('errors if we cannot mkdirp', function(done) { - var mkdirSpy = expect.spyOn(fs, 'mkdir').andCall(mockError); + it('errors if we cannot mkdirp', function (done) { + var mkdirSpy = sinon.stub(fs, 'mkdir').callsFake(mockError); var file = new File({ base: inputBase, @@ -1084,22 +1121,19 @@ describe('.dest()', function() { }); function assert(err) { - expect(err).toExist(); - expect(mkdirSpy.calls.length).toEqual(1); + expect(err).toEqual(expect.anything()); + expect(mkdirSpy.callCount).toEqual(1); done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - ], assert); + pipeline([from([file]), vfs.dest(outputBase)], assert); }); - it('errors if vinyl object is a directory and we cannot mkdirp', function(done) { + it('errors if vinyl object is a directory and we cannot mkdirp', function (done) { var ogMkdir = fs.mkdir; - var mkdirSpy = expect.spyOn(fs, 'mkdir').andCall(function() { - if (mkdirSpy.calls.length > 1) { + var mkdirSpy = sinon.stub(fs, 'mkdir').callsFake(function () { + if (mkdirSpy.callCount > 1) { mockError.apply(this, arguments); } else { ogMkdir.apply(this, arguments); @@ -1116,19 +1150,16 @@ describe('.dest()', function() { }); function assert(err) { - expect(err).toExist(); - expect(mkdirSpy.calls.length).toEqual(2); + expect(err).toEqual(expect.anything()); + expect(mkdirSpy.callCount).toEqual(2); done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - ], assert); + pipeline([from([file]), vfs.dest(outputBase)], assert); }); // TODO: is this correct behavior? had to adjust it - it('does not error if vinyl object is a directory and we cannot open it', function(done) { + it('does not error if vinyl object is a directory and we cannot open it', function (done) { var file = new File({ base: inputBase, path: inputDirpath, @@ -1144,15 +1175,11 @@ describe('.dest()', function() { expect(exists).toEqual(true); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('errors if vinyl object is a directory and open errors', function(done) { - var openSpy = expect.spyOn(fs, 'open').andCall(mockError); + it('errors if vinyl object is a directory and open errors', function (done) { + var openSpy = sinon.stub(fs, 'open').callsFake(mockError); var file = new File({ base: inputBase, @@ -1164,21 +1191,18 @@ describe('.dest()', function() { }); function assert(err) { - expect(err).toExist(); - expect(openSpy.calls.length).toEqual(1); + expect(err).toEqual(expect.anything()); + expect(openSpy.callCount).toEqual(1); done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - ], assert); + pipeline([from([file]), vfs.dest(outputBase)], assert); }); - it('errors if content stream errors', function(done) { - var contentStream = from(function(size, cb) { - cb(new Error('mocked error')); - }); + it('errors if content stream errors', function (done) { + var error = new Error('mocked error'); + + var contentStream = fromError(error); var file = new File({ base: inputBase, @@ -1187,17 +1211,14 @@ describe('.dest()', function() { }); function assert(err) { - expect(err).toExist(); + expect(err).toBe(error); done(); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - ], assert); + pipeline([from([file]), vfs.dest(outputBase)], assert); }); - it('does not pass options on to through2', function(done) { + it('does not pass options on to stream.Tranform', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -1205,21 +1226,20 @@ describe('.dest()', function() { }); // Reference: https://github.com/gulpjs/vinyl-fs/issues/153 - var read = expect.createSpy().andReturn(false); + var read = sinon.fake.returns(false); function assert() { // Called never because it's not a valid option - expect(read.calls.length).toEqual(0); + expect(read.callCount).toEqual(0); } - pipe([ - from.obj([file]), - vfs.dest(outputBase, { read: read }), - concat(assert), - ], done); + pipeline( + [from([file]), vfs.dest(outputBase, { read: read }), concatArray(assert)], + done + ); }); - it('does not marshall a Vinyl object with isSymbolic method', function(done) { + it('does not marshall a Vinyl object with isSymbolic method', function (done) { var file = new File({ base: outputBase, path: outputPath, @@ -1227,20 +1247,13 @@ describe('.dest()', function() { function assert(files) { expect(files.length).toEqual(1); - // Avoid comparing stats because they get reflected - delete files[0].stat; - expect(files[0]).toMatch(file); - expect(files[0]).toBe(file); + expect(files[0]).toEqual(file); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); - it('marshalls a Vinyl object without isSymbolic to a newer Vinyl', function(done) { + it('marshalls a Vinyl object without isSymbolic to a newer Vinyl', function (done) { var file = new File({ base: outputBase, path: outputPath, @@ -1251,15 +1264,11 @@ describe('.dest()', function() { function assert(files) { expect(files.length).toEqual(1); // Avoid comparing stats because they get reflected - delete files[0].stat; - expect(files[0]).toMatch(file); - expect(files[0]).toNotBe(file); + files[0].stat = file.stat; + expect(files[0]).toMatchObject(file); + expect(files[0]).not.toBe(file); } - pipe([ - from.obj([file]), - vfs.dest(outputBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(outputBase), concatArray(assert)], done); }); }); diff --git a/test/file-operations.js b/test/file-operations.js index 0385d920..11cbc848 100644 --- a/test/file-operations.js +++ b/test/file-operations.js @@ -6,7 +6,7 @@ var buffer = require('buffer'); var fs = require('graceful-fs'); var File = require('vinyl'); var expect = require('expect'); -var miss = require('mississippi'); +var sinon = require('sinon'); var mkdirp = require('fs-mkdirp-stream/mkdirp'); var fo = require('../lib/file-operations'); @@ -21,6 +21,7 @@ var isWindows = require('./utils/is-windows'); var applyUmask = require('./utils/apply-umask'); var testStreams = require('./utils/test-streams'); var testConstants = require('./utils/test-constants'); +var describeStreams = require('./utils/suite'); var closeFd = fo.closeFd; var isOwner = fo.isOwner; @@ -37,11 +38,6 @@ var reflectLinkStat = fo.reflectLinkStat; var updateMetadata = fo.updateMetadata; var createWriteStream = fo.createWriteStream; -var pipe = miss.pipe; -var from = miss.from; - -var string = testStreams.string; - var outputBase = testConstants.outputBase; var inputPath = testConstants.inputPath; var neInputDirpath = testConstants.neInputDirpath; @@ -53,8 +49,7 @@ var clean = cleanup(outputBase); function noop() {} -describe('isOwner', function() { - +describe('isOwner', function () { var ownerStat = { uid: 9001, }; @@ -66,7 +61,7 @@ describe('isOwner', function() { var getuidSpy; var geteuidSpy; - beforeEach(function(done) { + beforeEach(function (done) { if (typeof process.geteuid !== 'function') { process.geteuid = noop; } @@ -76,14 +71,24 @@ describe('isOwner', function() { process.getuid = noop; } - getuidSpy = expect.spyOn(process, 'getuid').andReturn(ownerStat.uid); - geteuidSpy = expect.spyOn(process, 'geteuid').andReturn(ownerStat.uid); + getuidSpy = sinon.stub(process, 'getuid').returns(ownerStat.uid); + geteuidSpy = sinon.stub(process, 'geteuid').returns(ownerStat.uid); done(); }); - afterEach(function(done) { - expect.restoreSpies(); + afterEach(function (done) { + // Because there are cases that delete process.geteuid or process.getuid, + // though an error occurs in sinon.restore if a spied function is + // undefined. + if (process.geteuid === undefined) { + process.geteuid = geteuidSpy; + } + if (process.getuid === undefined) { + process.getuid = getuidSpy; + } + + sinon.restore(); if (process.geteuid === noop) { delete process.geteuid; @@ -99,27 +104,26 @@ describe('isOwner', function() { // TODO: test for having neither - it('uses process.geteuid() when available', function(done) { - + it('uses process.geteuid() when available', function (done) { isOwner(ownerStat); - expect(getuidSpy.calls.length).toEqual(0); - expect(geteuidSpy.calls.length).toEqual(1); + expect(getuidSpy.callCount).toEqual(0); + expect(geteuidSpy.callCount).toEqual(1); done(); }); - it('uses process.getuid() when geteuid() is not available', function(done) { + it('uses process.getuid() when geteuid() is not available', function (done) { delete process.geteuid; isOwner(ownerStat); - expect(getuidSpy.calls.length).toEqual(1); + expect(getuidSpy.callCount).toEqual(1); done(); }); - it('returns false when non-root and non-owner', function(done) { + it('returns false when non-root and non-owner', function (done) { var result = isOwner(nonOwnerStat); expect(result).toEqual(false); @@ -127,7 +131,7 @@ describe('isOwner', function() { done(); }); - it('returns true when owner and non-root', function(done) { + it('returns true when owner and non-root', function (done) { var result = isOwner(ownerStat); expect(result).toEqual(true); @@ -135,8 +139,9 @@ describe('isOwner', function() { done(); }); - it('returns true when non-owner but root', function(done) { - expect.spyOn(process, 'geteuid').andReturn(0); // 0 is root uid + it('returns true when non-owner but root', function (done) { + process.geteuid.restore(); + sinon.stub(process, 'geteuid').returns(0); var result = isOwner(nonOwnerStat); @@ -146,9 +151,8 @@ describe('isOwner', function() { }); }); -describe('isValidUnixId', function() { - - it('returns true if the given id is a valid unix id', function(done) { +describe('isValidUnixId', function () { + it('returns true if the given id is a valid unix id', function (done) { var result = isValidUnixId(1000); expect(result).toEqual(true); @@ -156,7 +160,7 @@ describe('isValidUnixId', function() { done(); }); - it('returns false if the given id is not a number', function(done) { + it('returns false if the given id is not a number', function (done) { var result = isValidUnixId('root'); expect(result).toEqual(false); @@ -164,7 +168,7 @@ describe('isValidUnixId', function() { done(); }); - it('returns false when the given id is less than 0', function(done) { + it('returns false when the given id is less than 0', function (done) { var result = isValidUnixId(-1); expect(result).toEqual(false); @@ -173,9 +177,8 @@ describe('isValidUnixId', function() { }); }); -describe('getFlags', function() { - - it('returns wx if overwrite is false and append is false', function(done) { +describe('getFlags', function () { + it('returns wx if overwrite is false and append is false', function (done) { var result = getFlags({ overwrite: false, append: false, @@ -186,7 +189,7 @@ describe('getFlags', function() { done(); }); - it('returns w if overwrite is true and append is false', function(done) { + it('returns w if overwrite is true and append is false', function (done) { var result = getFlags({ overwrite: true, append: false, @@ -197,7 +200,7 @@ describe('getFlags', function() { done(); }); - it('returns ax if overwrite is false and append is true', function(done) { + it('returns ax if overwrite is false and append is true', function (done) { var result = getFlags({ overwrite: false, append: true, @@ -208,7 +211,7 @@ describe('getFlags', function() { done(); }); - it('returns a if overwrite is true and append is true', function(done) { + it('returns a if overwrite is true and append is true', function (done) { var result = getFlags({ overwrite: true, append: true, @@ -220,9 +223,8 @@ describe('getFlags', function() { }); }); -describe('isFatalOverwriteError', function() { - - it('returns false if not given any error', function(done) { +describe('isFatalOverwriteError', function () { + it('returns false if not given any error', function (done) { var result = isFatalOverwriteError(null); expect(result).toEqual(false); @@ -230,7 +232,7 @@ describe('isFatalOverwriteError', function() { done(); }); - it('returns true if code != EEXIST', function(done) { + it('returns true if code != EEXIST', function (done) { var result = isFatalOverwriteError({ code: 'EOTHER' }); expect(result).toEqual(true); @@ -238,7 +240,7 @@ describe('isFatalOverwriteError', function() { done(); }); - it('returns false if code == EEXIST and flags == wx', function(done) { + it('returns false if code == EEXIST and flags == wx', function (done) { var result = isFatalOverwriteError({ code: 'EEXIST' }, 'wx'); expect(result).toEqual(false); @@ -246,7 +248,7 @@ describe('isFatalOverwriteError', function() { done(); }); - it('returns false if code == EEXIST and flags == ax', function(done) { + it('returns false if code == EEXIST and flags == ax', function (done) { var result = isFatalOverwriteError({ code: 'EEXIST' }, 'ax'); expect(result).toEqual(false); @@ -254,7 +256,7 @@ describe('isFatalOverwriteError', function() { done(); }); - it('returns true if error.code == EEXIST and flags == w', function(done) { + it('returns true if error.code == EEXIST and flags == w', function (done) { var result = isFatalOverwriteError({ code: 'EEXIST' }, 'w'); expect(result).toEqual(true); @@ -262,7 +264,7 @@ describe('isFatalOverwriteError', function() { done(); }); - it('returns true if error.code == EEXIST and flags == a', function(done) { + it('returns true if error.code == EEXIST and flags == a', function (done) { var result = isFatalOverwriteError({ code: 'EEXIST' }, 'a'); expect(result).toEqual(true); @@ -271,9 +273,8 @@ describe('isFatalOverwriteError', function() { }); }); -describe('isFatalUnlinkError', function() { - - it('returns false if not given any error', function(done) { +describe('isFatalUnlinkError', function () { + it('returns false if not given any error', function (done) { var result = isFatalUnlinkError(null); expect(result).toEqual(false); @@ -281,7 +282,7 @@ describe('isFatalUnlinkError', function() { done(); }); - it('returns false if code == ENOENT', function(done) { + it('returns false if code == ENOENT', function (done) { var result = isFatalUnlinkError({ code: 'ENOENT' }, 'wx'); expect(result).toEqual(false); @@ -289,19 +290,17 @@ describe('isFatalUnlinkError', function() { done(); }); - it('returns true if code != ENOENT', function(done) { + it('returns true if code != ENOENT', function (done) { var result = isFatalUnlinkError({ code: 'EOTHER' }); expect(result).toEqual(true); done(); }); - }); -describe('getModeDiff', function() { - - it('returns 0 if both modes are the same', function(done) { +describe('getModeDiff', function () { + it('returns 0 if both modes are the same', function (done) { var fsMode = applyUmask('777'); var vfsMode = applyUmask('777'); @@ -312,7 +311,7 @@ describe('getModeDiff', function() { done(); }); - it('returns 0 if vinyl mode is not a number', function(done) { + it('returns 0 if vinyl mode is not a number', function (done) { var fsMode = applyUmask('777'); var vfsMode = undefined; @@ -323,7 +322,7 @@ describe('getModeDiff', function() { done(); }); - it('returns a value greater than 0 if modes are different', function(done) { + it('returns a value greater than 0 if modes are different', function (done) { var fsMode = applyUmask('777'); var vfsMode = applyUmask('744'); @@ -334,7 +333,7 @@ describe('getModeDiff', function() { done(); }); - it('returns the proper diff', function(done) { + it('returns the proper diff', function (done) { var fsMode = applyUmask('777'); var vfsMode = applyUmask('744'); var expectedDiff = applyUmask('33'); @@ -346,7 +345,7 @@ describe('getModeDiff', function() { done(); }); - it('does not matter the order of diffing', function(done) { + it('does not matter the order of diffing', function (done) { var fsMode = applyUmask('655'); var vfsMode = applyUmask('777'); var expectedDiff = applyUmask('122'); @@ -358,7 +357,7 @@ describe('getModeDiff', function() { done(); }); - it('includes the sticky/setuid/setgid bits', function(done) { + it('includes the sticky/setuid/setgid bits', function (done) { var fsMode = applyUmask('1777'); var vfsMode = applyUmask('4777'); var expectedDiff = applyUmask('5000'); @@ -371,9 +370,8 @@ describe('getModeDiff', function() { }); }); -describe('getTimesDiff', function() { - - it('returns undefined if vinyl mtime is not a valid date', function(done) { +describe('getTimesDiff', function () { + it('returns undefined if vinyl mtime is not a valid date', function (done) { var fsStat = { mtime: new Date(), }; @@ -388,7 +386,7 @@ describe('getTimesDiff', function() { done(); }); - it('returns undefined if vinyl mtime & atime are both equal to counterparts', function(done) { + it('returns undefined if vinyl mtime & atime are both equal to counterparts', function (done) { var now = Date.now(); var fsStat = { mtime: new Date(now), @@ -407,7 +405,7 @@ describe('getTimesDiff', function() { }); // TODO: is this proper/expected? - it('returns undefined if vinyl mtimes equals the counterpart and atimes are null', function(done) { + it('returns undefined if vinyl mtimes equals the counterpart and atimes are null', function (done) { var now = Date.now(); var fsStat = { mtime: new Date(now), @@ -425,7 +423,7 @@ describe('getTimesDiff', function() { done(); }); - it('returns a diff object if mtimes do not match', function(done) { + it('returns a diff object if mtimes do not match', function (done) { var now = Date.now(); var then = now - 1000; var fsStat = { @@ -446,7 +444,7 @@ describe('getTimesDiff', function() { done(); }); - it('returns a diff object if atimes do not match', function(done) { + it('returns a diff object if atimes do not match', function (done) { var now = Date.now(); var then = now - 1000; var fsStat = { @@ -469,7 +467,7 @@ describe('getTimesDiff', function() { done(); }); - it('returns the fs atime if the vinyl atime is invalid', function(done) { + it('returns the fs atime if the vinyl atime is invalid', function (done) { var now = Date.now(); var fsStat = { mtime: new Date(now), @@ -492,7 +490,7 @@ describe('getTimesDiff', function() { }); // TODO: is this proper/expected? - it('makes atime diff undefined if fs and vinyl atime are invalid', function(done) { + it('makes atime diff undefined if fs and vinyl atime are invalid', function (done) { var now = Date.now(); var fsStat = { mtime: new Date(now), @@ -515,9 +513,8 @@ describe('getTimesDiff', function() { }); }); -describe('getOwnerDiff', function() { - - it('returns undefined if vinyl uid & gid are invalid', function(done) { +describe('getOwnerDiff', function () { + it('returns undefined if vinyl uid & gid are invalid', function (done) { var fsStat = { uid: 1000, gid: 1000, @@ -534,7 +531,7 @@ describe('getOwnerDiff', function() { done(); }); - it('returns undefined if vinyl uid & gid are both equal to counterparts', function(done) { + it('returns undefined if vinyl uid & gid are both equal to counterparts', function (done) { var fsStat = { uid: 1000, gid: 1000, @@ -551,7 +548,7 @@ describe('getOwnerDiff', function() { done(); }); - it('returns a diff object if uid or gid do not match', function(done) { + it('returns a diff object if uid or gid do not match', function (done) { var fsStat = { uid: 1000, gid: 1000, @@ -578,14 +575,14 @@ describe('getOwnerDiff', function() { gid: 1001, }; - var result = getOwnerDiff(fsStat, vfsStat); + result = getOwnerDiff(fsStat, vfsStat); expect(result).toEqual(expected); done(); }); - it('returns the fs uid if the vinyl uid is invalid', function(done) { + it('returns the fs uid if the vinyl uid is invalid', function (done) { var fsStat = { uid: 1000, gid: 1000, @@ -603,19 +600,19 @@ describe('getOwnerDiff', function() { expect(result).toEqual(expected); - var vfsStat = { + vfsStat = { uid: -1, gid: 1001, }; - var result = getOwnerDiff(fsStat, vfsStat); + result = getOwnerDiff(fsStat, vfsStat); expect(result).toEqual(expected); done(); }); - it('returns the fs gid if the vinyl gid is invalid', function(done) { + it('returns the fs gid if the vinyl gid is invalid', function (done) { var fsStat = { uid: 1000, gid: 1000, @@ -633,19 +630,19 @@ describe('getOwnerDiff', function() { expect(result).toEqual(expected); - var vfsStat = { + vfsStat = { uid: 1001, gid: -1, }; - var result = getOwnerDiff(fsStat, vfsStat); + result = getOwnerDiff(fsStat, vfsStat); expect(result).toEqual(expected); done(); }); - it('returns undefined if fs and vinyl uid are invalid', function(done) { + it('returns undefined if fs and vinyl uid are invalid', function (done) { var fsStat = { uid: undefined, gid: 1000, @@ -659,23 +656,23 @@ describe('getOwnerDiff', function() { expect(result).toEqual(undefined); - var fsStat = { + fsStat = { uid: -1, gid: 1000, }; - var vfsStat = { + vfsStat = { uid: -1, gid: 1001, }; - var result = getOwnerDiff(fsStat, vfsStat); + result = getOwnerDiff(fsStat, vfsStat); expect(result).toEqual(undefined); done(); }); - it('returns undefined if fs and vinyl gid are invalid', function(done) { + it('returns undefined if fs and vinyl gid are invalid', function (done) { var fsStat = { uid: 1000, gid: undefined, @@ -698,7 +695,7 @@ describe('getOwnerDiff', function() { gid: -1, }; - var result = getOwnerDiff(fsStat, vfsStat); + result = getOwnerDiff(fsStat, vfsStat); expect(result).toEqual(undefined); @@ -706,65 +703,65 @@ describe('getOwnerDiff', function() { }); }); -describe('closeFd', function() { +describe('closeFd', function () { // This is just a very large number since node broke our tests by disallowing -1 // We're also doing some hacky version matching because node 0.12 accepts 10000 on Windows (and fails the test) var invalidFd = process.version[1] === '0' ? -1 : 10000; - it('calls the callback with propagated error if fd is not a number', function(done) { + it('calls the callback with propagated error if fd is not a number', function (done) { var propagatedError = new Error(); - closeFd(propagatedError, null, function(err) { + closeFd(propagatedError, null, function (err) { expect(err).toEqual(propagatedError); done(); }); }); - it('calls the callback with close error if no error to propagate', function(done) { - closeFd(null, invalidFd, function(err) { - expect(err).toExist(); + it('calls the callback with close error if no error to propagate', function (done) { + closeFd(null, invalidFd, function (err) { + expect(err).toEqual(expect.anything()); done(); }); }); - it('calls the callback with propagated error if close errors', function(done) { + it('calls the callback with propagated error if close errors', function (done) { var propagatedError = new Error(); - closeFd(propagatedError, invalidFd, function(err) { + closeFd(propagatedError, invalidFd, function (err) { expect(err).toEqual(propagatedError); done(); }); }); - it('calls the callback with propagated error if close succeeds', function(done) { + it('calls the callback with propagated error if close succeeds', function (done) { var propagatedError = new Error(); var fd = fs.openSync(inputPath, 'r'); - var closeSpy = expect.spyOn(fs, 'close').andCallThrough(); + var closeSpy = sinon.spy(fs, 'close'); - closeFd(propagatedError, fd, function(err) { + closeFd(propagatedError, fd, function (err) { closeSpy.restore(); - expect(closeSpy.calls.length).toEqual(1); + expect(closeSpy.callCount).toEqual(1); expect(err).toEqual(propagatedError); done(); }); }); - it('calls the callback with no error if close succeeds & no propagated error', function(done) { + it('calls the callback with no error if close succeeds & no propagated error', function (done) { var fd = fs.openSync(inputPath, 'r'); - var spy = expect.spyOn(fs, 'close').andCallThrough(); + var spy = sinon.spy(fs, 'close'); - closeFd(null, fd, function(err) { - spy.restore(); + closeFd(null, fd, function (err) { + sinon.restore(); - expect(spy.calls.length).toEqual(1); + expect(spy.callCount).toEqual(1); expect(err).toEqual(undefined); done(); @@ -772,21 +769,20 @@ describe('closeFd', function() { }); }); -describe('writeFile', function() { - +describe('writeFile', function () { beforeEach(clean); afterEach(clean); - beforeEach(function(done) { + beforeEach(function (done) { mkdirp(outputBase, done); }); - it('writes a file to the filesystem, does not close and returns the fd', function(done) { - writeFile(outputPath, new Buffer(contents), function(err, fd) { - expect(err).toNotExist(); + it('writes a file to the filesystem, does not close and returns the fd', function (done) { + writeFile(outputPath, Buffer.from(contents), function (err, fd) { + expect(err).not.toEqual(expect.anything()); expect(typeof fd === 'number').toEqual(true); - fs.close(fd, function() { + fs.close(fd, function () { var written = fs.readFileSync(outputPath, 'utf8'); expect(written).toEqual(contents); @@ -796,14 +792,14 @@ describe('writeFile', function() { }); }); - it('defaults to writing files with 0666 mode', function(done) { + it('defaults to writing files with 0666 mode', function (done) { var expected = applyUmask('666'); - writeFile(outputPath, new Buffer(contents), function(err, fd) { - expect(err).toNotExist(); + writeFile(outputPath, Buffer.from(contents), function (err, fd) { + expect(err).not.toEqual(expect.anything()); expect(typeof fd === 'number').toEqual(true); - fs.close(fd, function() { + fs.close(fd, function () { expect(statMode(outputPath)).toEqual(expected); done(); @@ -811,7 +807,7 @@ describe('writeFile', function() { }); }); - it('accepts a different mode in options', function(done) { + it('accepts a different mode in options', function (done) { // Changing the mode of a file is not supported by node.js in Windows. if (isWindows) { this.skip(); @@ -823,11 +819,11 @@ describe('writeFile', function() { mode: expected, }; - writeFile(outputPath, new Buffer(contents), options, function(err, fd) { - expect(err).toNotExist(); + writeFile(outputPath, Buffer.from(contents), options, function (err, fd) { + expect(err).not.toEqual(expect.anything()); expect(typeof fd === 'number').toEqual(true); - fs.close(fd, function() { + fs.close(fd, function () { expect(statMode(outputPath)).toEqual(expected); done(); @@ -835,42 +831,49 @@ describe('writeFile', function() { }); }); - it('defaults to opening files with write flag', function(done) { + it('defaults to opening files with write flag', function (done) { var length = contents.length; - writeFile(outputPath, new Buffer(contents), function(err, fd) { - expect(err).toNotExist(); + writeFile(outputPath, Buffer.from(contents), function (err, fd) { + expect(err).not.toEqual(expect.anything()); expect(typeof fd === 'number').toEqual(true); - fs.read(fd, new Buffer(length), 0, length, 0, function(readErr) { - expect(readErr).toExist(); + fs.read(fd, Buffer.alloc(length), 0, length, 0, function (readErr) { + expect(readErr).toEqual(expect.anything()); fs.close(fd, done); }); }); }); - it('accepts a different flags in options', function(done) { + it('accepts a different flags in options', function (done) { var length = contents.length; var options = { flags: 'w+', }; - writeFile(outputPath, new Buffer(contents), options, function(err, fd) { - expect(err).toNotExist(); + writeFile(outputPath, Buffer.from(contents), options, function (err, fd) { + expect(err).not.toEqual(expect.anything()); expect(typeof fd === 'number').toEqual(true); - fs.read(fd, new Buffer(length), 0, length, 0, function(readErr, _, written) { - expect(readErr).toNotExist(); + fs.read( + fd, + Buffer.alloc(length), + 0, + length, + 0, + function (readErr, _, written) { + expect(readErr).not.toEqual(expect.anything()); - expect(written.toString()).toEqual(contents); + expect(written.toString()).toEqual(contents); - fs.close(fd, done); - }); + fs.close(fd, done); + } + ); }); }); - it('appends to a file if append flag is given', function(done) { + it('appends to a file if append flag is given', function (done) { var initial = 'test'; var toWrite = '-a-thing'; @@ -882,11 +885,11 @@ describe('writeFile', function() { flags: 'a', }; - writeFile(outputPath, new Buffer(toWrite), options, function(err, fd) { - expect(err).toNotExist(); + writeFile(outputPath, Buffer.from(toWrite), options, function (err, fd) { + expect(err).not.toEqual(expect.anything()); expect(typeof fd === 'number').toEqual(true); - fs.close(fd, function() { + fs.close(fd, function () { var written = fs.readFileSync(outputPath, 'utf8'); expect(written).toEqual(expected); @@ -896,54 +899,54 @@ describe('writeFile', function() { }); }); - it('does not pass a file descriptor if open call errors', function(done) { + it('does not pass a file descriptor if open call errors', function (done) { var notExistDir = path.join(__dirname, './not-exist-dir/writeFile.txt'); - writeFile(notExistDir, new Buffer(contents), function(err, fd) { - expect(err).toExist(); + writeFile(notExistDir, Buffer.from(contents), function (err, fd) { + expect(err).toEqual(expect.anything()); expect(typeof fd === 'number').toEqual(false); done(); }); }); - it('passes a file descriptor if write call errors', function(done) { + it('passes a file descriptor if write call errors', function (done) { var options = { flags: 'r', }; - writeFile(inputPath, new Buffer(contents), options, function(err, fd) { - expect(err).toExist(); + writeFile(inputPath, Buffer.from(contents), options, function (err, fd) { + expect(err).toEqual(expect.anything()); expect(typeof fd === 'number').toEqual(true); fs.close(fd, done); }); }); - it('passes an error if called with string as data', function(done) { - writeFile(outputPath, contents, function(err) { - expect(err).toExist(); + it('passes an error if called with string as data', function (done) { + writeFile(outputPath, contents, function (err) { + expect(err).toEqual(expect.anything()); done(); }); }); - it('does not error on SlowBuffer', function(done) { + it('does not error on SlowBuffer', function (done) { if (!buffer.SlowBuffer) { this.skip(); return; } var length = contents.length; - var buf = new Buffer(contents); + var buf = Buffer.from(contents); var content = new buffer.SlowBuffer(length); buf.copy(content, 0, 0, length); - writeFile(outputPath, content, function(err, fd) { - expect(err).toNotExist(); + writeFile(outputPath, content, function (err, fd) { + expect(err).not.toEqual(expect.anything()); expect(typeof fd === 'number').toEqual(true); - fs.close(fd, function() { + fs.close(fd, function () { var written = fs.readFileSync(outputPath, 'utf8'); expect(written).toEqual(contents); @@ -953,9 +956,9 @@ describe('writeFile', function() { }); }); - it('does not error if options is falsey', function(done) { - writeFile(outputPath, new Buffer(contents), null, function(err, fd) { - expect(err).toNotExist(); + it('does not error if options is falsey', function (done) { + writeFile(outputPath, Buffer.from(contents), null, function (err, fd) { + expect(err).not.toEqual(expect.anything()); expect(typeof fd === 'number').toEqual(true); fs.close(fd, done); @@ -963,37 +966,35 @@ describe('writeFile', function() { }); }); -describe('reflectStat', function() { - +describe('reflectStat', function () { beforeEach(clean); afterEach(clean); - beforeEach(function(done) { + beforeEach(function (done) { mkdirp(outputBase, done); }); - it('passes the error if stat fails', function(done) { - + it('passes the error if stat fails', function (done) { var file = new File(); - reflectStat(neInputDirpath, file, function(err) { - expect(err).toExist(); + reflectStat(neInputDirpath, file, function (err) { + expect(err).toEqual(expect.anything()); done(); }); }); - it('updates the vinyl with filesystem stats', function(done) { + it('updates the vinyl with filesystem stats', function (done) { var file = new File(); fs.symlinkSync(inputPath, symlinkPath); - reflectStat(symlinkPath, file, function() { + reflectStat(symlinkPath, file, function () { // There appears to be a bug in the Windows implementation which causes // the sync versions of stat and lstat to return unsigned 32-bit ints // whilst the async versions returns signed 32-bit ints... This affects // dev but possibly others as well? - fs.stat(symlinkPath, function(err, stat) { + fs.stat(symlinkPath, function (err, stat) { expect(file.stat).toEqual(stat); done(); @@ -1002,37 +1003,35 @@ describe('reflectStat', function() { }); }); -describe('reflectLinkStat', function() { - +describe('reflectLinkStat', function () { beforeEach(clean); afterEach(clean); - beforeEach(function(done) { + beforeEach(function (done) { mkdirp(outputBase, done); }); - it('passes the error if lstat fails', function(done) { - + it('passes the error if lstat fails', function (done) { var file = new File(); - reflectLinkStat(neInputDirpath, file, function(err) { - expect(err).toExist(); + reflectLinkStat(neInputDirpath, file, function (err) { + expect(err).toEqual(expect.anything()); done(); }); }); - it('updates the vinyl with filesystem symbolic stats', function(done) { + it('updates the vinyl with filesystem symbolic stats', function (done) { var file = new File(); fs.symlinkSync(inputPath, symlinkPath); - reflectLinkStat(symlinkPath, file, function() { + reflectLinkStat(symlinkPath, file, function () { // There appears to be a bug in the Windows implementation which causes // the sync versions of stat and lstat to return unsigned 32-bit ints // whilst the async versions returns signed 32-bit ints... This affects // dev but possibly others as well? - fs.lstat(symlinkPath, function(err, stat) { + fs.lstat(symlinkPath, function (err, stat) { expect(file.stat).toEqual(stat); done(); @@ -1041,16 +1040,15 @@ describe('reflectLinkStat', function() { }); }); -describe('updateMetadata', function() { - +describe('updateMetadata', function () { beforeEach(clean); afterEach(clean); - beforeEach(function(done) { + beforeEach(function (done) { mkdirp(outputBase, done); }); - afterEach(function(done) { + afterEach(function (done) { if (process.geteuid === noop) { delete process.geteuid; } @@ -1058,7 +1056,7 @@ describe('updateMetadata', function() { done(); }); - it('passes the error if fstat fails', function(done) { + it('passes the error if fstat fails', function (done) { // Changing the time of a directory errors in Windows. // Changing the mode of a file is not supported by node.js in Windows. // Windows is treated as though it does not have permission to make these operations. @@ -1076,14 +1074,14 @@ describe('updateMetadata', function() { stat: {}, }); - updateMetadata(fd, file, function(err) { - expect(err).toExist(); + updateMetadata(fd, file, function (err) { + expect(err).toEqual(expect.anything()); done(); }); }); - it('updates the vinyl object with fs stats', function(done) { + it('updates the vinyl object with fs stats', function (done) { if (isWindows) { this.skip(); return; @@ -1099,9 +1097,9 @@ describe('updateMetadata', function() { var fd = fs.openSync(outputPath, 'w+'); var stats = fs.fstatSync(fd); - updateMetadata(fd, file, function() { + updateMetadata(fd, file, function () { // Not sure why .toEqual doesn't match these - Object.keys(file.stat).forEach(function(key) { + Object.keys(file.stat).forEach(function (key) { expect(file.stat[key]).toEqual(stats[key]); }); @@ -1109,7 +1107,7 @@ describe('updateMetadata', function() { }); }); - it('does not touch the fs if nothing to update', function(done) { + it('does not touch the fs if nothing to update', function (done) { if (isWindows) { this.skip(); return; @@ -1122,20 +1120,20 @@ describe('updateMetadata', function() { stat: {}, }); - var fchmodSpy = expect.spyOn(fs, 'fchmod').andCallThrough(); - var futimesSpy = expect.spyOn(fs, 'futimes').andCallThrough(); + var fchmodSpy = sinon.spy(fs, 'fchmod'); + var futimesSpy = sinon.spy(fs, 'futimes'); var fd = fs.openSync(outputPath, 'w+'); - updateMetadata(fd, file, function() { - expect(fchmodSpy.calls.length).toEqual(0); - expect(futimesSpy.calls.length).toEqual(0); + updateMetadata(fd, file, function () { + expect(fchmodSpy.callCount).toEqual(0); + expect(futimesSpy.callCount).toEqual(0); fs.close(fd, done); }); }); - it('does not touch the fs if process is not owner of the file', function(done) { + it('does not touch the fs if process is not owner of the file', function (done) { if (isWindows) { this.skip(); return; @@ -1156,27 +1154,27 @@ describe('updateMetadata', function() { }, }); - expect.spyOn(process, 'geteuid').andReturn(9002); - var fchmodSpy = expect.spyOn(fs, 'fchmod').andCallThrough(); - var futimesSpy = expect.spyOn(fs, 'futimes').andCallThrough(); + sinon.stub(process, 'geteuid').returns(9002); + var fchmodSpy = sinon.spy(fs, 'fchmod'); + var futimesSpy = sinon.spy(fs, 'futimes'); var fd = fs.openSync(outputPath, 'w+'); - updateMetadata(fd, file, function() { - expect(fchmodSpy.calls.length).toEqual(0); - expect(futimesSpy.calls.length).toEqual(0); + updateMetadata(fd, file, function () { + expect(fchmodSpy.callCount).toEqual(0); + expect(futimesSpy.callCount).toEqual(0); fs.close(fd, done); }); }); - it('updates times on fs and vinyl object if there is a diff', function(done) { + it('updates times on fs and vinyl object if there is a diff', function (done) { if (isWindows) { this.skip(); return; } - var futimesSpy = expect.spyOn(fs, 'futimes').andCallThrough(); + var futimesSpy = sinon.spy(fs, 'futimes'); // Use new atime/mtime var atime = new Date(Date.now() - 2048); @@ -1196,12 +1194,12 @@ describe('updateMetadata', function() { var fd = fs.openSync(outputPath, 'w+'); - updateMetadata(fd, file, function() { - expect(futimesSpy.calls.length).toEqual(1); + updateMetadata(fd, file, function () { + expect(futimesSpy.callCount).toEqual(1); // Var stats = fs.fstatSync(fd); - var atimeSpy = futimesSpy.calls[0].arguments[1]; - var mtimeSpy = futimesSpy.calls[0].arguments[2]; + var atimeSpy = futimesSpy.getCall(0).args[1]; + var mtimeSpy = futimesSpy.getCall(0).args[2]; expect(file.stat.mtime).toEqual(new Date(mtimeEarlier)); expect(mtimeSpy.getTime()).toEqual(mtimeEarlier); @@ -1212,13 +1210,13 @@ describe('updateMetadata', function() { }); }); - it('forwards futimes error and descriptor upon error', function(done) { + it('forwards futimes error and descriptor upon error', function (done) { if (isWindows) { this.skip(); return; } - var futimesSpy = expect.spyOn(fs, 'futimes').andCall(mockError); + var futimesSpy = sinon.stub(fs, 'futimes').callsFake(mockError); var now = Date.now(); var then = now - 1000; @@ -1236,21 +1234,21 @@ describe('updateMetadata', function() { var fd = fs.openSync(outputPath, 'w+'); expect(typeof fd === 'number').toEqual(true); - updateMetadata(fd, file, function(err) { - expect(err).toExist(); - expect(futimesSpy.calls.length).toEqual(1); + updateMetadata(fd, file, function (err) { + expect(err).toEqual(expect.anything()); + expect(futimesSpy.callCount).toEqual(1); fs.close(fd, done); }); }); - it('updates the mode on fs and vinyl object if there is a diff', function(done) { + it('updates the mode on fs and vinyl object if there is a diff', function (done) { if (isWindows) { this.skip(); return; } - var fchmodSpy = expect.spyOn(fs, 'fchmod').andCallThrough(); + var fchmodSpy = sinon.spy(fs, 'fchmod'); var mode = applyUmask('777'); @@ -1265,8 +1263,8 @@ describe('updateMetadata', function() { var fd = fs.openSync(outputPath, 'w+'); - updateMetadata(fd, file, function() { - expect(fchmodSpy.calls.length).toEqual(1); + updateMetadata(fd, file, function () { + expect(fchmodSpy.callCount).toEqual(1); var stats = fs.fstatSync(fd); expect(file.stat.mode).toEqual(stats.mode); @@ -1274,14 +1272,13 @@ describe('updateMetadata', function() { }); }); - - it('updates the sticky bit on mode on fs and vinyl object if there is a diff', function(done) { + it('updates the sticky bit on mode on fs and vinyl object if there is a diff', function (done) { if (isWindows) { this.skip(); return; } - var fchmodSpy = expect.spyOn(fs, 'fchmod').andCallThrough(); + var fchmodSpy = sinon.spy(fs, 'fchmod'); var mode = applyUmask('1777'); @@ -1296,8 +1293,8 @@ describe('updateMetadata', function() { var fd = fs.openSync(outputPath, 'w+'); - updateMetadata(fd, file, function() { - expect(fchmodSpy.calls.length).toEqual(1); + updateMetadata(fd, file, function () { + expect(fchmodSpy.callCount).toEqual(1); var stats = fs.fstatSync(fd); expect(file.stat.mode).toEqual(stats.mode); @@ -1305,7 +1302,7 @@ describe('updateMetadata', function() { }); }); - it('forwards fchmod error and descriptor upon error', function(done) { + it('forwards fchmod error and descriptor upon error', function (done) { if (isWindows) { this.skip(); return; @@ -1324,24 +1321,24 @@ describe('updateMetadata', function() { var fd = fs.openSync(outputPath, 'w+'); - var fchmodSpy = expect.spyOn(fs, 'fchmod').andCall(mockError); + var fchmodSpy = sinon.stub(fs, 'fchmod').callsFake(mockError); - updateMetadata(fd, file, function(err) { - expect(err).toExist(); - expect(fchmodSpy.calls.length).toEqual(1); + updateMetadata(fd, file, function (err) { + expect(err).toEqual(expect.anything()); + expect(fchmodSpy.callCount).toEqual(1); fs.close(fd, done); }); }); - it('updates the mode & times on fs and vinyl object if there is a diff', function(done) { + it('updates the mode & times on fs and vinyl object if there is a diff', function (done) { if (isWindows) { this.skip(); return; } - var fchmodSpy = expect.spyOn(fs, 'fchmod').andCallThrough(); - var futimesSpy = expect.spyOn(fs, 'futimes').andCallThrough(); + var fchmodSpy = sinon.spy(fs, 'fchmod'); + var futimesSpy = sinon.spy(fs, 'futimes'); // Use new atime/mtime var atime = new Date(Date.now() - 2048); @@ -1364,12 +1361,12 @@ describe('updateMetadata', function() { var fd = fs.openSync(outputPath, 'w+'); - updateMetadata(fd, file, function() { - expect(fchmodSpy.calls.length).toEqual(1); - expect(futimesSpy.calls.length).toEqual(1); + updateMetadata(fd, file, function () { + expect(fchmodSpy.callCount).toEqual(1); + expect(futimesSpy.callCount).toEqual(1); - var atimeSpy = futimesSpy.calls[0].arguments[1]; - var mtimeSpy = futimesSpy.calls[0].arguments[2]; + var atimeSpy = futimesSpy.getCall(0).args[1]; + var mtimeSpy = futimesSpy.getCall(0).args[2]; expect(file.stat.mtime).toEqual(new Date(mtimeEarlier)); expect(mtimeSpy.getTime()).toEqual(mtimeEarlier); @@ -1380,7 +1377,7 @@ describe('updateMetadata', function() { }); }); - it('forwards fchmod error and descriptor through futimes if there is a time diff', function(done) { + it('forwards fchmod error and descriptor through futimes if there is a time diff', function (done) { if (isWindows) { this.skip(); return; @@ -1388,10 +1385,10 @@ describe('updateMetadata', function() { var mockedErr = new Error('mocked error'); - var fchmodSpy = expect.spyOn(fs, 'fchmod').andCall(function(fd, mode, cb) { + var fchmodSpy = sinon.stub(fs, 'fchmod').callsFake(function (fd, mode, cb) { cb(mockedErr); }); - var futimesSpy = expect.spyOn(fs, 'futimes').andCallThrough(); + var futimesSpy = sinon.spy(fs, 'futimes'); var now = Date.now(); var then = now - 1000; @@ -1410,11 +1407,11 @@ describe('updateMetadata', function() { var fd = fs.openSync(outputPath, 'w'); - updateMetadata(fd, file, function(err) { - expect(err).toExist(); + updateMetadata(fd, file, function (err) { + expect(err).toEqual(expect.anything()); expect(err).toEqual(mockedErr); - expect(fchmodSpy.calls.length).toEqual(1); - expect(futimesSpy.calls.length).toEqual(1); + expect(fchmodSpy.callCount).toEqual(1); + expect(futimesSpy.callCount).toEqual(1); fs.close(fd, done); }); @@ -1423,32 +1420,35 @@ describe('updateMetadata', function() { // TODO: forward fchown error tests }); -describe('createWriteStream', function() { +describeStreams('createWriteStream', function (stream) { + var from = stream.Readable.from; + var pipeline = stream.pipeline; + + var streamUtils = testStreams(stream); + var chunks = streamUtils.chunks; beforeEach(clean); afterEach(clean); - beforeEach(function(done) { + beforeEach(function (done) { // For some reason, the outputDir sometimes exists on Windows // So we use our mkdirp to create it mkdirp(outputBase, done); }); - it('accepts just a file path and writes to it', function(done) { - + it('accepts just a file path and writes to it', function (done) { function assert(err) { var outputContents = fs.readFileSync(outputPath, 'utf8'); expect(outputContents).toEqual(contents); done(err); } - pipe([ - from([contents]), - createWriteStream(outputPath), - ], assert); + pipeline([from([contents]), createWriteStream(outputPath)], assert); }); - it('accepts just a file path and writes a large file to it', function(done) { + it('accepts just a file path and writes a large file to it', function (done) { + this.timeout(0); + var size = 40000; function assert(err) { @@ -1458,13 +1458,10 @@ describe('createWriteStream', function() { done(err); } - pipe([ - string(size), - createWriteStream(outputPath), - ], assert); + pipeline([chunks(size), createWriteStream(outputPath)], assert); }); - it('accepts flags option', function(done) { + it('accepts flags option', function (done) { // Write 13 stars then 12345 because the length of expected is 13 fs.writeFileSync(outputPath, '*************12345'); @@ -1474,14 +1471,17 @@ describe('createWriteStream', function() { done(err); } - pipe([ - from([contents]), - // Replaces from the beginning of the file - createWriteStream(outputPath, { flags: 'r+' }), - ], assert); + pipeline( + [ + from([contents]), + // Replaces from the beginning of the file + createWriteStream(outputPath, { flags: 'r+' }), + ], + assert + ); }); - it('accepts append flag as option & places cursor at the end', function(done) { + it('accepts append flag as option & places cursor at the end', function (done) { fs.writeFileSync(outputPath, '12345'); function assert(err) { @@ -1490,16 +1490,21 @@ describe('createWriteStream', function() { done(err); } - pipe([ - from([contents]), - // Appends to the end of the file - createWriteStream(outputPath, { flags: 'a' }), - ], assert); + pipeline( + [ + from([contents]), + // Appends to the end of the file + createWriteStream(outputPath, { flags: 'a' }), + ], + assert + ); }); - it('accepts mode option', function(done) { + it('accepts mode option', function (done) { if (isWindows) { - console.log('Changing the mode of a file is not supported by node.js in Windows.'); + console.log( + 'Changing the mode of a file is not supported by node.js in Windows.' + ); this.skip(); return; } @@ -1511,13 +1516,13 @@ describe('createWriteStream', function() { done(err); } - pipe([ - from([contents]), - createWriteStream(outputPath, { mode: mode }), - ], assert); + pipeline( + [from([contents]), createWriteStream(outputPath, { mode: mode })], + assert + ); }); - it('uses default file mode if no mode options', function(done) { + it('uses default file mode if no mode options', function (done) { var defaultMode = applyUmask(DEFAULT_FILE_MODE); function assert(err) { @@ -1525,16 +1530,13 @@ describe('createWriteStream', function() { done(err); } - pipe([ - from([contents]), - createWriteStream(outputPath), - ], assert); + pipeline([from([contents]), createWriteStream(outputPath)], assert); }); - it('accepts a flush function that is called before close emitted', function(done) { + it('accepts a flush function that is called before close emitted', function (done) { var flushCalled = false; - var outStream = createWriteStream(outputPath, {}, function(fd, cb) { + var outStream = createWriteStream(outputPath, {}, function (fd, cb) { flushCalled = true; cb(); }); @@ -1544,16 +1546,13 @@ describe('createWriteStream', function() { done(err); } - pipe([ - from([contents]), - outStream, - ], assert); + pipeline([from([contents]), outStream], assert); }); - it('can specify flush without options argument', function(done) { + it('can specify flush without options argument', function (done) { var flushCalled = false; - var outStream = createWriteStream(outputPath, function(fd, cb) { + var outStream = createWriteStream(outputPath, function (fd, cb) { flushCalled = true; cb(); }); @@ -1563,17 +1562,14 @@ describe('createWriteStream', function() { done(err); } - pipe([ - from([contents]), - outStream, - ], assert); + pipeline([from([contents]), outStream], assert); }); - it('passes the file descriptor to flush', function(done) { + it('passes the file descriptor to flush', function (done) { var flushCalled = false; - var outStream = createWriteStream(outputPath, function(fd, cb) { - expect(fd).toBeA('number'); + var outStream = createWriteStream(outputPath, function (fd, cb) { + expect(typeof fd).toEqual('number'); flushCalled = true; cb(); }); @@ -1583,19 +1579,16 @@ describe('createWriteStream', function() { done(err); } - pipe([ - from([contents]), - outStream, - ], assert); + pipeline([from([contents]), outStream], assert); }); - it('passes a callback to flush to call when work is done', function(done) { + it('passes a callback to flush to call when work is done', function (done) { var flushCalled = false; var timeoutCalled = false; - var outStream = createWriteStream(outputPath, function(fd, cb) { + var outStream = createWriteStream(outputPath, function (fd, cb) { flushCalled = true; - setTimeout(function() { + setTimeout(function () { timeoutCalled = true; cb(); }, 250); @@ -1607,38 +1600,32 @@ describe('createWriteStream', function() { done(err); } - pipe([ - from([contents]), - outStream, - ], assert); + pipeline([from([contents]), outStream], assert); }); - it('emits an error if open fails', function(done) { + it('emits an error if open fails', function (done) { var badOutputPath = path.join(outputBase, './non-exist/test.coffee'); function assert(err) { - expect(err).toBeAn(Error); + expect(err).toBeInstanceOf(Error); done(); } - pipe([ - from([contents]), - createWriteStream(badOutputPath), - ], assert); + pipeline([from([contents]), createWriteStream(badOutputPath)], assert); }); - it('emits an error if write fails', function(done) { + it('emits an error if write fails', function (done) { // Create the file so it can be opened with `r` fs.writeFileSync(outputPath, contents); function assert(err) { - expect(err).toBeAn(Error); + expect(err).toBeInstanceOf(Error); done(); } - pipe([ - from([contents]), - createWriteStream(outputPath, { flags: 'r' }), - ], assert); + pipeline( + [from([contents]), createWriteStream(outputPath, { flags: 'r' })], + assert + ); }); }); diff --git a/test/integration.js b/test/integration.js index 9022bb92..6ed884ee 100644 --- a/test/integration.js +++ b/test/integration.js @@ -3,7 +3,6 @@ var path = require('path'); var fs = require('graceful-fs'); -var miss = require('mississippi'); var expect = require('expect'); var vfs = require('../'); @@ -12,20 +11,13 @@ var cleanup = require('./utils/cleanup'); var isWindows = require('./utils/is-windows'); var testStreams = require('./utils/test-streams'); var testConstants = require('./utils/test-constants'); - -var pipe = miss.pipe; -var concat = miss.concat; - -var count = testStreams.count; +var describeStreams = require('./utils/suite'); var base = testConstants.outputBase; var inputDirpath = testConstants.inputDirpath; var outputDirpath = testConstants.outputDirpath; var symlinkDirpath = testConstants.symlinkDirpath; var inputBase = path.join(base, './in/'); -var inputDirpath = testConstants.inputDirpath; -var outputDirpath = testConstants.outputDirpath; -var symlinkDirpath = testConstants.symlinkDirpath; var inputGlob = path.join(inputBase, './*.txt'); var outputBase = path.join(base, './out/'); var outputSymlink = path.join(symlinkDirpath, './foo'); @@ -34,12 +26,17 @@ var content = testConstants.contents; var clean = cleanup(base); -describe('integrations', function() { +describeStreams('integrations', function (stream) { + var pipeline = stream.pipeline; + + var streamUtils = testStreams(stream); + var count = streamUtils.count; + var concatArray = streamUtils.concatArray; beforeEach(clean); afterEach(clean); - it('does not exhaust available file descriptors when streaming thousands of files', function(done) { + it('does not exhaust available file descriptors when streaming thousands of files', function (done) { // This can be a very slow test on boxes with slow disk i/o this.timeout(0); @@ -54,14 +51,17 @@ describe('integrations', function() { fs.writeFileSync(filepath, content); } - pipe([ - vfs.src(inputGlob, { buffer: false }), - count(expectedCount), - vfs.dest(outputBase), - ], done); + pipeline( + [ + vfs.src(inputGlob, { buffer: false }), + count(expectedCount), + vfs.dest(outputBase), + ], + done + ); }); - it('(*nix) sources a directory, creates a symlink and copies it', function(done) { + it('(*nix) sources a directory, creates a symlink and copies it', function (done) { if (isWindows) { this.skip(); return; @@ -77,15 +77,18 @@ describe('integrations', function() { expect(files[0].symlink).toEqual(inputDirpath); } - pipe([ - vfs.src(inputDirpath), - vfs.symlink(symlinkDirpath), - vfs.dest(outputDirpath), - concat(assert), - ], done); + pipeline( + [ + vfs.src(inputDirpath), + vfs.symlink(symlinkDirpath), + vfs.dest(outputDirpath), + concatArray(assert), + ], + done + ); }); - it('(windows) sources a directory, creates a junction and copies it', function(done) { + it('(windows) sources a directory, creates a junction and copies it', function (done) { if (!isWindows) { this.skip(); return; @@ -103,15 +106,18 @@ describe('integrations', function() { expect(files[0].symlink).toEqual(inputDirpath); } - pipe([ - vfs.src(inputDirpath), - vfs.symlink(symlinkDirpath), - vfs.dest(outputDirpath), - concat(assert), - ], done); + pipeline( + [ + vfs.src(inputDirpath), + vfs.symlink(symlinkDirpath), + vfs.dest(outputDirpath), + concatArray(assert), + ], + done + ); }); - it('(*nix) sources a symlink and copies it', function(done) { + it('(*nix) sources a symlink and copies it', function (done) { if (isWindows) { this.skip(); return; @@ -129,14 +135,17 @@ describe('integrations', function() { expect(files[0].symlink).toEqual(inputDirpath); } - pipe([ - vfs.src(outputSymlink, { resolveSymlinks: false }), - vfs.dest(outputDirpath), - concat(assert), - ], done); + pipeline( + [ + vfs.src(outputSymlink, { resolveSymlinks: false }), + vfs.dest(outputDirpath), + concatArray(assert), + ], + done + ); }); - it('(windows) sources a directory symlink and copies it', function(done) { + it('(windows) sources a directory symlink and copies it', function (done) { if (!isWindows) { this.skip(); return; @@ -156,14 +165,17 @@ describe('integrations', function() { expect(files[0].symlink).toEqual(inputDirpath); } - pipe([ - vfs.src(outputSymlink, { resolveSymlinks: false }), - vfs.dest(outputDirpath), - concat(assert), - ], done); + pipeline( + [ + vfs.src(outputSymlink, { resolveSymlinks: false }), + vfs.dest(outputDirpath), + concatArray(assert), + ], + done + ); }); - it('(windows) sources a junction and copies it', function(done) { + it('(windows) sources a junction and copies it', function (done) { if (!isWindows) { this.skip(); return; @@ -183,10 +195,13 @@ describe('integrations', function() { expect(files[0].symlink).toEqual(inputDirpath); } - pipe([ - vfs.src(outputSymlink, { resolveSymlinks: false }), - vfs.dest(outputDirpath), - concat(assert), - ], done); + pipeline( + [ + vfs.src(outputSymlink, { resolveSymlinks: false }), + vfs.dest(outputDirpath), + concatArray(assert), + ], + done + ); }); }); diff --git a/test/not-owned.js b/test/not-owned.js index 9dbbed39..15bf6d79 100644 --- a/test/not-owned.js +++ b/test/not-owned.js @@ -3,17 +3,15 @@ var fs = require('graceful-fs'); var File = require('vinyl'); var expect = require('expect'); -var miss = require('mississippi'); +var sinon = require('sinon'); var vfs = require('../'); var cleanup = require('./utils/cleanup'); var applyUmask = require('./utils/apply-umask'); +var testStreams = require('./utils/test-streams'); var testConstants = require('./utils/test-constants'); - -var from = miss.from; -var pipe = miss.pipe; -var concat = miss.concat; +var describeStreams = require('./utils/suite'); var notOwnedBase = testConstants.notOwnedBase; var notOwnedPath = testConstants.notOwnedPath; @@ -21,9 +19,12 @@ var contents = testConstants.contents; var clean = cleanup(); -describe('.dest() on not owned files', function() { +describeStreams('.dest() on not owned files', function (stream) { + var from = stream.Readable.from; + var pipeline = stream.pipeline; - var fileStats = fs.statSync(notOwnedPath); + var streamUtils = testStreams(stream); + var concatArray = streamUtils.concatArray; beforeEach(clean); afterEach(clean); @@ -31,6 +32,8 @@ describe('.dest() on not owned files', function() { var seenActions = false; function needsAction() { + var fileStats = fs.statSync(notOwnedPath); + var problems = []; var actions = []; if (fileStats.uid !== 0) { @@ -53,61 +56,53 @@ describe('.dest() on not owned files', function() { return false; } - it('does not error if mtime is different', function(done) { + it('does not error if mtime is different', function (done) { if (needsAction()) { this.skip(); return; } - var futimesSpy = expect.spyOn(fs, 'futimes').andCallThrough(); + var futimesSpy = sinon.spy(fs, 'futimes'); var earlier = Date.now() - 1000; var file = new File({ base: notOwnedBase, path: notOwnedPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { mtime: new Date(earlier), }, }); function assert() { - expect(futimesSpy.calls.length).toEqual(0); + expect(futimesSpy.callCount).toEqual(0); } - pipe([ - from.obj([file]), - vfs.dest(notOwnedBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(notOwnedBase), concatArray(assert)], done); }); - it('does not error if mode is different', function(done) { + it('does not error if mode is different', function (done) { if (needsAction()) { this.skip(); return; } - var fchmodSpy = expect.spyOn(fs, 'fchmod').andCallThrough(); + var fchmodSpy = sinon.spy(fs, 'fchmod'); var file = new File({ base: notOwnedBase, path: notOwnedPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: { mode: applyUmask('777'), }, }); function assert() { - expect(fchmodSpy.calls.length).toEqual(0); + expect(fchmodSpy.callCount).toEqual(0); } - pipe([ - from.obj([file]), - vfs.dest(notOwnedBase), - concat(assert), - ], done); + pipeline([from([file]), vfs.dest(notOwnedBase), concatArray(assert)], done); }); }); diff --git a/test/src-symlinks.js b/test/src-symlinks.js index a4f61d75..3d0f744b 100644 --- a/test/src-symlinks.js +++ b/test/src-symlinks.js @@ -2,15 +2,14 @@ var fs = require('graceful-fs'); var expect = require('expect'); -var miss = require('mississippi'); +var sinon = require('sinon'); var vfs = require('../'); var cleanup = require('./utils/cleanup'); +var testStreams = require('./utils/test-streams'); var testConstants = require('./utils/test-constants'); - -var pipe = miss.pipe; -var concat = miss.concat; +var describeStreams = require('./utils/suite'); var outputBase = testConstants.outputBase; var inputPath = testConstants.inputPath; @@ -26,12 +25,16 @@ var symlinkNestedSecond = testConstants.symlinkNestedSecond; var clean = cleanup(outputBase); -describe('.src() with symlinks', function() { +describeStreams('.src() with symlinks', function (stream) { + var pipeline = stream.pipeline; + + var streamUtils = testStreams(stream); + var concatArray = streamUtils.concatArray; beforeEach(clean); afterEach(clean); - beforeEach(function(done) { + beforeEach(function (done) { fs.mkdirSync(outputBase); fs.mkdirSync(outputDirpath); fs.symlinkSync(inputDirpath, symlinkDirpath); @@ -43,7 +46,7 @@ describe('.src() with symlinks', function() { done(); }); - it('resolves symlinks correctly', function(done) { + it('resolves symlinks correctly', function (done) { function assert(files) { expect(files.length).toEqual(1); // The path should be the symlink itself @@ -55,13 +58,10 @@ describe('.src() with symlinks', function() { expect(files[0].stat.isFile()).toEqual(true); } - pipe([ - vfs.src(symlinkNestedFirst), - concat(assert), - ], done); + pipeline([vfs.src(symlinkNestedFirst), concatArray(assert)], done); }); - it('resolves directory symlinks correctly', function(done) { + it('resolves directory symlinks correctly', function (done) { function assert(files) { expect(files.length).toEqual(1); // The path should be the symlink itself @@ -73,13 +73,10 @@ describe('.src() with symlinks', function() { expect(files[0].stat.isDirectory()).toEqual(true); } - pipe([ - vfs.src(symlinkDirpath), - concat(assert), - ], done); + pipeline([vfs.src(symlinkDirpath), concatArray(assert)], done); }); - it('resolves nested symlinks to directories correctly', function(done) { + it('resolves nested symlinks to directories correctly', function (done) { function assert(files) { expect(files.length).toEqual(1); // The path should be the symlink itself @@ -91,13 +88,10 @@ describe('.src() with symlinks', function() { expect(files[0].stat.isDirectory()).toEqual(true); } - pipe([ - vfs.src(symlinkMultiDirpathSecond), - concat(assert), - ], done); + pipeline([vfs.src(symlinkMultiDirpathSecond), concatArray(assert)], done); }); - it('preserves file symlinks with resolveSymlinks option set to false', function(done) { + it('preserves file symlinks with resolveSymlinks option set to false', function (done) { var expectedRelativeSymlinkPath = fs.readlinkSync(symlinkPath); function assert(files) { @@ -106,13 +100,13 @@ describe('.src() with symlinks', function() { expect(files[0].symlink).toEqual(expectedRelativeSymlinkPath); } - pipe([ - vfs.src(symlinkPath, { resolveSymlinks: false }), - concat(assert), - ], done); + pipeline( + [vfs.src(symlinkPath, { resolveSymlinks: false }), concatArray(assert)], + done + ); }); - it('preserves directory symlinks with resolveSymlinks option set to false', function(done) { + it('preserves directory symlinks with resolveSymlinks option set to false', function (done) { var expectedRelativeSymlinkPath = fs.readlinkSync(symlinkDirpath); function assert(files) { @@ -121,17 +115,19 @@ describe('.src() with symlinks', function() { expect(files[0].symlink).toEqual(expectedRelativeSymlinkPath); } - pipe([ - vfs.src(symlinkDirpath, { resolveSymlinks: false }), - concat(assert), - ], done); + pipeline( + [ + vfs.src(symlinkDirpath, { resolveSymlinks: false }), + concatArray(assert), + ], + done + ); }); - it('receives a file with symbolic link stats when resolveSymlinks is a function', function(done) { - + it('receives a file with symbolic link stats when resolveSymlinks is a function', function (done) { function resolveSymlinks(file) { - expect(file).toExist(); - expect(file.stat).toExist(); + expect(file).toEqual(expect.anything()); + expect(file.stat).toEqual(expect.anything()); expect(file.stat.isSymbolicLink()).toEqual(true); return true; @@ -144,23 +140,28 @@ describe('.src() with symlinks', function() { expect(files[0].stat.isFile()).toEqual(true); } - pipe([ - vfs.src(symlinkNestedFirst, { resolveSymlinks: resolveSymlinks }), - concat(assert), - ], done); + pipeline( + [ + vfs.src(symlinkNestedFirst, { resolveSymlinks: resolveSymlinks }), + concatArray(assert), + ], + done + ); }); - it('only calls resolveSymlinks once-per-file if it is a function', function(done) { - - var spy = expect.createSpy().andReturn(true); + it('only calls resolveSymlinks once-per-file if it is a function', function (done) { + var spy = sinon.fake.returns(true); function assert() { - expect(spy.calls.length).toEqual(1); + expect(spy.callCount).toEqual(1); } - pipe([ - vfs.src(symlinkNestedFirst, { resolveSymlinks: spy }), - concat(assert), - ], done); + pipeline( + [ + vfs.src(symlinkNestedFirst, { resolveSymlinks: spy }), + concatArray(assert), + ], + done + ); }); }); diff --git a/test/src.js b/test/src.js index effc46ea..8542fc5d 100644 --- a/test/src.js +++ b/test/src.js @@ -5,16 +5,13 @@ var path = require('path'); var fs = require('graceful-fs'); var File = require('vinyl'); var expect = require('expect'); -var miss = require('mississippi'); +var sinon = require('sinon'); var vfs = require('../'); +var testStreams = require('./utils/test-streams'); var testConstants = require('./utils/test-constants'); - -var pipe = miss.pipe; -var from = miss.from; -var concat = miss.concat; -var through = miss.through; +var describeStreams = require('./utils/suite'); var inputBase = testConstants.inputBase; var inputPath = testConstants.inputPath; @@ -30,92 +27,95 @@ var encodedContents = testConstants.encodedContents; var bomContents = testConstants.bomContents; var contents = testConstants.contents; -describe('.src()', function() { +describeStreams('.src()', function (stream) { + var from = stream.Readable.from; + var pipeline = stream.pipeline; + + var streamUtils = testStreams(stream); + var concatArray = streamUtils.concatArray; + var compareContents = streamUtils.compareContents; - it('throws on invalid glob (empty)', function(done) { + it('throws on invalid glob (empty)', function (done) { var stream; try { stream = vfs.src(); } catch (err) { - expect(err).toExist(); - expect(stream).toNotExist(); + expect(err).toEqual(expect.anything()); + expect(stream).not.toEqual(expect.anything()); done(); } }); - it('throws on invalid glob (empty string)', function(done) { + it('throws on invalid glob (empty string)', function (done) { var stream; try { stream = vfs.src(''); } catch (err) { - expect(err).toExist(); - expect(stream).toNotExist(); + expect(err).toEqual(expect.anything()); + expect(stream).not.toEqual(expect.anything()); done(); } }); - it('throws on invalid glob (number)', function(done) { + it('throws on invalid glob (number)', function (done) { var stream; try { stream = vfs.src(123); } catch (err) { - expect(err).toExist(); - expect(stream).toNotExist(); + expect(err).toEqual(expect.anything()); + expect(stream).not.toEqual(expect.anything()); done(); } }); - it('throws on invalid glob (nested array)', function(done) { + it('throws on invalid glob (nested array)', function (done) { var stream; try { stream = vfs.src([['./fixtures/*.coffee']]); } catch (err) { - expect(err).toExist(); - expect(stream).toNotExist(); - expect(err.message).toInclude('Invalid glob argument'); + expect(err).toEqual(expect.anything()); + expect(stream).not.toEqual(expect.anything()); + expect(err.message).toMatch('Invalid glob argument'); done(); } }); - it('throws on invalid glob (empty string in array)', function(done) { + it('throws on invalid glob (empty string in array)', function (done) { var stream; try { stream = vfs.src(['']); } catch (err) { - expect(err).toExist(); - expect(stream).toNotExist(); + expect(err).toEqual(expect.anything()); + expect(stream).not.toEqual(expect.anything()); done(); } }); - it('throws on invalid glob (empty array)', function(done) { + it('throws on invalid glob (empty array)', function (done) { var stream; try { stream = vfs.src([]); } catch (err) { - expect(err).toExist(); - expect(stream).toNotExist(); + expect(err).toEqual(expect.anything()); + expect(stream).not.toEqual(expect.anything()); done(); } }); - it('emits an error on file not existing', function(done) { + it('emits an error on file not existing', function (done) { function assert(err) { - expect(err).toExist(); + expect(err).toEqual(expect.anything()); done(); } - pipe([ - vfs.src('./fixtures/noexist.coffee'), - concat(), - ], assert); + pipeline([vfs.src('./fixtures/noexist.coffee'), concatArray()], assert); }); - it('passes through writes', function(done) { + it('passes through writes', function (done) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), stat: fs.statSync(inputPath), }); @@ -128,40 +128,25 @@ describe('.src()', function() { srcStream.write(file); - pipe([ - srcStream, - concat(assert), - ], done); + pipeline([srcStream, concatArray(assert)], done); }); - it('removes BOM from utf8-encoded files by default (buffer)', function(done) { - var expectedContent = new Buffer(bomContents.replace('X', '8')); + it('removes BOM from utf8-encoded files by default (buffer)', function (done) { + var expectedContent = Buffer.from(bomContents.replace('X', '8')); function assert(files) { expect(files.length).toEqual(1); - expect(files[0].contents).toMatch(expectedContent); + expect(files[0].contents).toEqual(expectedContent); } - pipe([ - vfs.src(bomInputPath), - concat(assert), - ], done); + pipeline([vfs.src(bomInputPath), concatArray(assert)], done); }); - it('removes BOM from utf8-encoded files by default (stream)', function(done) { - var expectedContent = new Buffer(bomContents.replace('X', '8')); + it('removes BOM from utf8-encoded files by default (stream)', function (done) { + var expectedContent = Buffer.from(bomContents.replace('X', '8')); function assertContent(contents) { - expect(contents).toMatch(expectedContent); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContent); } function assert(files) { @@ -169,41 +154,35 @@ describe('.src()', function() { expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(bomInputPath, { buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(bomInputPath, { buffer: false }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); - it('does not remove BOM from utf8-encoded files if option is false (buffer)', function(done) { - var expectedContent = new Buffer('\ufeff' + bomContents.replace('X', '8')); + it('does not remove BOM from utf8-encoded files if option is false (buffer)', function (done) { + var expectedContent = Buffer.from('\ufeff' + bomContents.replace('X', '8')); function assert(files) { expect(files.length).toEqual(1); - expect(files[0].contents).toMatch(expectedContent); + expect(files[0].contents).toEqual(expectedContent); } - pipe([ - vfs.src(bomInputPath, { removeBOM: false }), - concat(assert), - ], done); + pipeline( + [vfs.src(bomInputPath, { removeBOM: false }), concatArray(assert)], + done + ); }); - it('does not remove BOM from utf8-encoded files if option is false (stream)', function(done) { - var expectedContent = new Buffer('\ufeff' + bomContents.replace('X', '8')); + it('does not remove BOM from utf8-encoded files if option is false (stream)', function (done) { + var expectedContent = Buffer.from('\ufeff' + bomContents.replace('X', '8')); function assertContent(contents) { - expect(contents).toMatch(expectedContent); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContent); } function assert(files) { @@ -211,41 +190,35 @@ describe('.src()', function() { expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(bomInputPath, { removeBOM: false, buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(bomInputPath, { removeBOM: false, buffer: false }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); - it('removes BOM from utf16be-encoded files by default (buffer)', function(done) { - var expectedContent = new Buffer(bomContents.replace('X', '16-BE')); + it('removes BOM from utf16be-encoded files by default (buffer)', function (done) { + var expectedContent = Buffer.from(bomContents.replace('X', '16-BE')); function assert(files) { expect(files.length).toEqual(1); - expect(files[0].contents).toMatch(expectedContent); + expect(files[0].contents).toEqual(expectedContent); } - pipe([ - vfs.src(beBomInputPath, { encoding: 'utf16be' }), - concat(assert), - ], done); + pipeline( + [vfs.src(beBomInputPath, { encoding: 'utf16be' }), concatArray(assert)], + done + ); }); - it('removes BOM from utf16be-encoded files by default (stream)', function(done) { - var expectedContent = new Buffer(bomContents.replace('X', '16-BE')); + it('removes BOM from utf16be-encoded files by default (stream)', function (done) { + var expectedContent = Buffer.from(bomContents.replace('X', '16-BE')); function assertContent(contents) { - expect(contents).toMatch(expectedContent); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContent); } function assert(files) { @@ -253,41 +226,42 @@ describe('.src()', function() { expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(beBomInputPath, { encoding: 'utf16be', buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(beBomInputPath, { encoding: 'utf16be', buffer: false }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); - it('does not remove BOM from utf16be-encoded files if option is false (buffer)', function(done) { - var expectedContent = new Buffer('\ufeff' + bomContents.replace('X', '16-BE')); + it('does not remove BOM from utf16be-encoded files if option is false (buffer)', function (done) { + var expectedContent = Buffer.from( + '\ufeff' + bomContents.replace('X', '16-BE') + ); function assert(files) { expect(files.length).toEqual(1); - expect(files[0].contents).toMatch(expectedContent); + expect(files[0].contents).toEqual(expectedContent); } - pipe([ - vfs.src(beBomInputPath, { encoding: 'utf16be', removeBOM: false }), - concat(assert), - ], done); + pipeline( + [ + vfs.src(beBomInputPath, { encoding: 'utf16be', removeBOM: false }), + concatArray(assert), + ], + done + ); }); - it('does not remove BOM from utf16be-encoded files if option is false (stream)', function(done) { - var expectedContent = new Buffer('\ufeff' + bomContents.replace('X', '16-BE')); + it('does not remove BOM from utf16be-encoded files if option is false (stream)', function (done) { + var expectedContent = Buffer.from( + '\ufeff' + bomContents.replace('X', '16-BE') + ); function assertContent(contents) { - expect(contents).toMatch(expectedContent); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContent); } function assert(files) { @@ -295,41 +269,39 @@ describe('.src()', function() { expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(beBomInputPath, { encoding: 'utf16be', removeBOM: false, buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(beBomInputPath, { + encoding: 'utf16be', + removeBOM: false, + buffer: false, + }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); - it('removes BOM from utf16le-encoded files by default (buffer)', function(done) { - var expectedContent = new Buffer(bomContents.replace('X', '16-LE')); + it('removes BOM from utf16le-encoded files by default (buffer)', function (done) { + var expectedContent = Buffer.from(bomContents.replace('X', '16-LE')); function assert(files) { expect(files.length).toEqual(1); - expect(files[0].contents).toMatch(expectedContent); + expect(files[0].contents).toEqual(expectedContent); } - pipe([ - vfs.src(leBomInputPath, { encoding: 'utf16le' }), - concat(assert), - ], done); + pipeline( + [vfs.src(leBomInputPath, { encoding: 'utf16le' }), concatArray(assert)], + done + ); }); - it('removes BOM from utf16le-encoded files by default (stream)', function(done) { - var expectedContent = new Buffer(bomContents.replace('X', '16-LE')); + it('removes BOM from utf16le-encoded files by default (stream)', function (done) { + var expectedContent = Buffer.from(bomContents.replace('X', '16-LE')); function assertContent(contents) { - expect(contents).toMatch(expectedContent); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContent); } function assert(files) { @@ -337,41 +309,42 @@ describe('.src()', function() { expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(leBomInputPath, { encoding: 'utf16le', buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(leBomInputPath, { encoding: 'utf16le', buffer: false }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); - it('does not remove BOM from utf16le-encoded files if option is false (buffer)', function(done) { - var expectedContent = new Buffer('\ufeff' + bomContents.replace('X', '16-LE')); + it('does not remove BOM from utf16le-encoded files if option is false (buffer)', function (done) { + var expectedContent = Buffer.from( + '\ufeff' + bomContents.replace('X', '16-LE') + ); function assert(files) { expect(files.length).toEqual(1); - expect(files[0].contents).toMatch(expectedContent); + expect(files[0].contents).toEqual(expectedContent); } - pipe([ - vfs.src(leBomInputPath, { encoding: 'utf16le', removeBOM: false }), - concat(assert), - ], done); + pipeline( + [ + vfs.src(leBomInputPath, { encoding: 'utf16le', removeBOM: false }), + concatArray(assert), + ], + done + ); }); - it('does not remove BOM from utf16le-encoded files if option is false (stream)', function(done) { - var expectedContent = new Buffer('\ufeff' + bomContents.replace('X', '16-LE')); + it('does not remove BOM from utf16le-encoded files if option is false (stream)', function (done) { + var expectedContent = Buffer.from( + '\ufeff' + bomContents.replace('X', '16-LE') + ); function assertContent(contents) { - expect(contents).toMatch(expectedContent); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContent); } function assert(files) { @@ -379,43 +352,41 @@ describe('.src()', function() { expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(leBomInputPath, { encoding: 'utf16le', removeBOM: false, buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(leBomInputPath, { + encoding: 'utf16le', + removeBOM: false, + buffer: false, + }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); // This goes for any non-UTF-8 encoding. // UTF-16-BE is enough to demonstrate this is done properly. - it('does not remove anything that looks like a utf8-encoded BOM from utf16be-encoded files (buffer)', function(done) { + it('does not remove anything that looks like a utf8-encoded BOM from utf16be-encoded files (buffer)', function (done) { var expectedContent = fs.readFileSync(beNotBomInputPath); function assert(files) { expect(files.length).toEqual(1); - expect(files[0].contents).toMatch(expectedContent); - }; + expect(files[0].contents).toEqual(expectedContent); + } - pipe([ - vfs.src(beNotBomInputPath), - concat(assert), - ], done); + pipeline( + [vfs.src(beNotBomInputPath, { encoding: false }), concatArray(assert)], + done + ); }); - it('does not remove anything that looks like a utf8-encoded BOM from utf16be-encoded files (stream)', function(done) { + it('does not remove anything that looks like a utf8-encoded BOM from utf16be-encoded files (stream)', function (done) { var expectedContent = fs.readFileSync(beNotBomInputPath); function assertContent(contents) { - expect(contents).toMatch(expectedContent); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContent); } function assert(files) { @@ -423,43 +394,37 @@ describe('.src()', function() { expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(beNotBomInputPath, { buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(beNotBomInputPath, { buffer: false, encoding: false }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); // This goes for any non-UTF-8 encoding. // UTF-16-LE is enough to demonstrate this is done properly. - it('does not remove anything that looks like a utf8-encoded BOM from utf16le-encoded files (buffer)', function(done) { + it('does not remove anything that looks like a utf8-encoded BOM from utf16le-encoded files (buffer)', function (done) { var expectedContent = fs.readFileSync(leNotBomInputPath); function assert(files) { expect(files.length).toEqual(1); - expect(files[0].contents).toMatch(expectedContent); + expect(files[0].contents).toEqual(expectedContent); } - pipe([ - vfs.src(leNotBomInputPath), - concat(assert), - ], done); + pipeline( + [vfs.src(leNotBomInputPath, { encoding: false }), concatArray(assert)], + done + ); }); - it('does not remove anything that looks like a utf8-encoded BOM from utf16le-encoded files (stream)', function(done) { + it('does not remove anything that looks like a utf8-encoded BOM from utf16le-encoded files (stream)', function (done) { var expectedContent = fs.readFileSync(leNotBomInputPath); function assertContent(contents) { - expect(contents).toMatch(expectedContent); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContent); } function assert(files) { @@ -467,41 +432,35 @@ describe('.src()', function() { expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(leNotBomInputPath, { buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(leNotBomInputPath, { buffer: false, encoding: false }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); - it('does not do any transcoding with encoding option set to false (buffer)', function(done) { + it('does not do any transcoding with encoding option set to false (buffer)', function (done) { var expectedContents = fs.readFileSync(ranBomInputPath); function assert(files) { expect(files.length).toEqual(1); - expect(files[0].contents).toMatch(expectedContents); + expect(files[0].contents).toEqual(expectedContents); } - pipe([ - vfs.src(ranBomInputPath, { encoding: false }), - concat(assert), - ], done); + pipeline( + [vfs.src(ranBomInputPath, { encoding: false }), concatArray(assert)], + done + ); }); - it('does not do any transcoding with encoding option set to false (stream)', function(done) { + it('does not do any transcoding with encoding option set to false (stream)', function (done) { var expectedContents = fs.readFileSync(ranBomInputPath); function assertContent(contents) { - expect(contents).toMatch(expectedContents); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContents); } function assert(files) { @@ -509,83 +468,70 @@ describe('.src()', function() { expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(ranBomInputPath, { encoding: false, buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(ranBomInputPath, { encoding: false, buffer: false }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); - it('does not remove utf8 BOM with encoding option set to false (buffer)', function(done) { + it('does not remove utf8 BOM with encoding option set to false (buffer)', function (done) { var expectedContents = fs.readFileSync(bomInputPath); function assert(files) { expect(files.length).toEqual(1); - expect(files[0].contents).toMatch(expectedContents); + expect(files[0].contents).toEqual(expectedContents); } - pipe([ - vfs.src(bomInputPath, { encoding: false }), - concat(assert), - ], done); + pipeline( + [vfs.src(bomInputPath, { encoding: false }), concatArray(assert)], + done + ); }); - it('does not remove utf8 BOM with encoding option set to false (stream)', function(done) { + it('does not remove utf8 BOM with encoding option set to false (stream)', function (done) { var expectedContents = fs.readFileSync(bomInputPath); function assertContent(contents) { - expect(contents).toMatch(expectedContents); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContents); } - function assert(files) { expect(files.length).toEqual(1); expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(bomInputPath, { encoding: false, buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(bomInputPath, { encoding: false, buffer: false }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); - it('transcodes gb2312 to utf8 with encoding option (buffer)', function(done) { - var expectedContents = new Buffer(encodedContents); + it('transcodes gb2312 to utf8 with encoding option (buffer)', function (done) { + var expectedContents = Buffer.from(encodedContents); function assert(files) { expect(files.length).toEqual(1); - expect(files[0].contents).toMatch(expectedContents); + expect(files[0].contents).toEqual(expectedContents); } - pipe([ - vfs.src(encodedInputPath, { encoding: 'gb2312' }), - concat(assert), - ], done); + pipeline( + [vfs.src(encodedInputPath, { encoding: 'gb2312' }), concatArray(assert)], + done + ); }); - it('transcodes gb2312 to utf8 with encoding option (stream)', function(done) { - var expectedContents = new Buffer(encodedContents); + it('transcodes gb2312 to utf8 with encoding option (stream)', function (done) { + var expectedContents = Buffer.from(encodedContents); function assertContent(contents) { - expect(contents).toMatch(expectedContents); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContents); } function assert(files) { @@ -593,74 +539,79 @@ describe('.src()', function() { expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(encodedInputPath, { encoding: 'gb2312', buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(encodedInputPath, { encoding: 'gb2312', buffer: false }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); - it('reports unsupported encoding errors (buffer)', function(done) { + it('reports unsupported encoding errors (buffer)', function (done) { function assert(files) { expect(files.length).toEqual(0); } function finish(err) { - expect(err).toExist(); + expect(err).toEqual(expect.anything()); expect(err.message).toEqual('Unsupported encoding: fubar42'); done(); } - pipe([ - vfs.src(inputPath, { encoding: 'fubar42' }), - concat(assert), - ], finish); + pipeline( + [vfs.src(inputPath, { encoding: 'fubar42' }), concatArray(assert)], + finish + ); }); - it('reports unsupported encoding errors (stream)', function(done) { + it('reports unsupported encoding errors (stream)', function (done) { function assert(files) { expect(files.length).toEqual(0); } function finish(err) { - expect(err).toExist(); + expect(err).toEqual(expect.anything()); expect(err.message).toEqual('Unsupported encoding: fubar42'); done(); } - pipe([ - vfs.src(inputPath, { encoding: 'fubar42', buffer: false }), - concat(assert), - ], finish); + pipeline( + [ + vfs.src(inputPath, { encoding: 'fubar42', buffer: false }), + concatArray(assert), + ], + finish + ); }); - - it('globs files with default settings', function(done) { + it('globs files with default settings', function (done) { function assert(files) { expect(files.length).toEqual(7); } - pipe([ - vfs.src('./fixtures/*.txt', { cwd: __dirname }), - concat(assert), - ], done); + pipeline( + [vfs.src('./fixtures/*.txt', { cwd: __dirname }), concatArray(assert)], + done + ); }); - it('globs files with default settings and relative cwd', function(done) { + it('globs files with default settings and relative cwd', function (done) { var cwd = path.relative(process.cwd(), __dirname); function assert(files) { expect(files.length).toEqual(7); } - pipe([ - vfs.src('./fixtures/*.txt', { cwd: cwd }), - concat(assert), - ], done); + pipeline( + [vfs.src('./fixtures/*.txt', { cwd: cwd }), concatArray(assert)], + done + ); }); // TODO: need to normalize the path of a directory vinyl object - it('globs a directory with default settings', function(done) { + it('globs a directory with default settings', function (done) { var inputDirGlob = path.join(inputBase, './f*/'); function assert(files) { @@ -669,13 +620,10 @@ describe('.src()', function() { expect(files[0].isDirectory()).toEqual(true); } - pipe([ - vfs.src(inputDirGlob), - concat(assert), - ], done); + pipeline([vfs.src(inputDirGlob), concatArray(assert)], done); }); - it('globs a directory with default settings and relative cwd', function(done) { + it('globs a directory with default settings and relative cwd', function (done) { var cwd = path.relative(process.cwd(), __dirname); function assert(files) { @@ -684,13 +632,13 @@ describe('.src()', function() { expect(files[0].isDirectory()).toEqual(true); } - pipe([ - vfs.src('./fixtures/f*/', { cwd: cwd }), - concat(assert), - ], done); + pipeline( + [vfs.src('./fixtures/f*/', { cwd: cwd }), concatArray(assert)], + done + ); }); - it('streams a directory with default settings', function(done) { + it('streams a directory with default settings', function (done) { function assert(files) { expect(files.length).toEqual(1); expect(files[0].path).toEqual(inputDirpath); @@ -698,27 +646,21 @@ describe('.src()', function() { expect(files[0].isDirectory()).toEqual(true); } - pipe([ - vfs.src(inputDirpath), - concat(assert), - ], done); + pipeline([vfs.src(inputDirpath), concatArray(assert)], done); }); - it('streams file with with no contents using read: false option', function(done) { + it('streams file with with no contents using read: false option', function (done) { function assert(files) { expect(files.length).toEqual(1); expect(files[0].path).toEqual(inputPath); expect(files[0].isNull()).toEqual(true); - expect(files[0].contents).toNotExist(); + expect(files[0].contents).toEqual(null); } - pipe([ - vfs.src(inputPath, { read: false }), - concat(assert), - ], done); + pipeline([vfs.src(inputPath, { read: false }), concatArray(assert)], done); }); - it('streams a file changed after since', function(done) { + it('streams a file changed after since', function (done) { var lastUpdateDate = new Date(+fs.statSync(inputPath).mtime - 1000); function assert(files) { @@ -726,39 +668,30 @@ describe('.src()', function() { expect(files[0].path).toEqual(inputPath); } - pipe([ - vfs.src(inputPath, { since: lastUpdateDate }), - concat(assert), - ], done); + pipeline( + [vfs.src(inputPath, { since: lastUpdateDate }), concatArray(assert)], + done + ); }); - it('does not stream a file changed before since', function(done) { + it('does not stream a file changed before since', function (done) { var lastUpdateDate = new Date(+fs.statSync(inputPath).mtime + 1000); function assert(files) { expect(files.length).toEqual(0); } - pipe([ - vfs.src(inputPath, { since: lastUpdateDate }), - concat(assert), - ], done); + pipeline( + [vfs.src(inputPath, { since: lastUpdateDate }), concatArray(assert)], + done + ); }); - it('streams a file with streaming contents', function(done) { + it('streams a file with streaming contents', function (done) { var expectedContent = fs.readFileSync(inputPath); function assertContent(contents) { - expect(contents).toMatch(expectedContent); - } - - function compareContents(file, enc, cb) { - pipe([ - file.contents, - concat(assertContent), - ], function(err) { - cb(err, file); - }); + expect(contents).toEqual(expectedContent); } function assert(files) { @@ -767,14 +700,17 @@ describe('.src()', function() { expect(files[0].isStream()).toEqual(true); } - pipe([ - vfs.src(inputPath, { buffer: false }), - through.obj(compareContents), - concat(assert), - ], done); + pipeline( + [ + vfs.src(inputPath, { buffer: false }), + compareContents(assertContent), + concatArray(assert), + ], + done + ); }); - it('can be used as a through stream and adds new files to the end', function(done) { + it('can be used as a through stream and adds new files to the end', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -787,37 +723,29 @@ describe('.src()', function() { expect(files[0]).toEqual(file); } - pipe([ - from.obj([file]), - vfs.src(inputPath), - concat(assert), - ], done); + pipeline([from([file]), vfs.src(inputPath), concatArray(assert)], done); }); - it('can be used at beginning and in the middle', function(done) { + it('can be used at beginning and in the middle', function (done) { function assert(files) { expect(files.length).toEqual(2); } - pipe([ - vfs.src(inputPath), - vfs.src(inputPath), - concat(assert), - ], done); + pipeline( + [vfs.src(inputPath), vfs.src(inputPath), concatArray(assert)], + done + ); }); - it('does not pass options on to through2', function(done) { + it('does not pass options on to stream.Transform', function (done) { // Reference: https://github.com/gulpjs/vinyl-fs/issues/153 - var read = expect.createSpy().andReturn(false); + var read = sinon.fake.returns(false); function assert() { // Called once to resolve the option - expect(read.calls.length).toEqual(1); + expect(read.callCount).toEqual(1); } - pipe([ - vfs.src(inputPath, { read: read }), - concat(assert), - ], done); + pipeline([vfs.src(inputPath, { read: read }), concatArray(assert)], done); }); }); diff --git a/test/symlink.js b/test/symlink.js index 606d92de..61481792 100644 --- a/test/symlink.js +++ b/test/symlink.js @@ -5,7 +5,7 @@ var path = require('path'); var fs = require('graceful-fs'); var File = require('vinyl'); var expect = require('expect'); -var miss = require('mississippi'); +var sinon = require('sinon'); var vfs = require('../'); @@ -15,13 +15,7 @@ var testStreams = require('./utils/test-streams'); var always = require('./utils/always'); var testConstants = require('./utils/test-constants'); var breakPrototype = require('./utils/break-prototype'); - -var from = miss.from; -var pipe = miss.pipe; -var concat = miss.concat; - -var count = testStreams.count; -var slowCount = testStreams.slowCount; +var describeStreams = require('./utils/suite'); function noop() {} @@ -36,30 +30,41 @@ var contents = testConstants.contents; var clean = cleanup(outputBase); -describe('symlink stream', function() { +describeStreams('symlink stream', function (stream) { + var from = stream.Readable.from; + var pipeline = stream.pipeline; + + var streamUtils = testStreams(stream); + var count = streamUtils.count; + var slowCount = streamUtils.slowCount; + var concatArray = streamUtils.concatArray; beforeEach(clean); afterEach(clean); - it('throws on no folder argument', function(done) { + it('throws on no folder argument', function (done) { function noFolder() { vfs.symlink(); } - expect(noFolder).toThrow('Invalid symlink() folder argument. Please specify a non-empty string or a function.'); + expect(noFolder).toThrow( + 'Invalid symlink() folder argument. Please specify a non-empty string or a function.' + ); done(); }); - it('throws on empty string folder argument', function(done) { + it('throws on empty string folder argument', function (done) { function emptyFolder() { vfs.symlink(''); } - expect(emptyFolder).toThrow('Invalid symlink() folder argument. Please specify a non-empty string or a function.'); + expect(emptyFolder).toThrow( + 'Invalid symlink() folder argument. Please specify a non-empty string or a function.' + ); done(); }); - it('passes through writes with cwd', function(done) { + it('passes through writes with cwd', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -68,18 +73,21 @@ describe('symlink stream', function() { function assert(files) { expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].cwd).toEqual(__dirname, 'cwd should have changed'); + expect(files).toContain(file); + expect(files[0].cwd).toEqual(__dirname); } - pipe([ - from.obj([file]), - vfs.symlink(outputRelative, { cwd: __dirname }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputRelative, { cwd: __dirname }), + concatArray(assert), + ], + done + ); }); - it('passes through writes with default cwd', function(done) { + it('passes through writes with default cwd', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -88,18 +96,17 @@ describe('symlink stream', function() { function assert(files) { expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].cwd).toEqual(process.cwd(), 'cwd should not have changed'); + expect(files).toContain(file); + expect(files[0].cwd).toEqual(process.cwd()); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase), - concat(assert), - ], done); + pipeline( + [from([file]), vfs.symlink(outputBase), concatArray(assert)], + done + ); }); - it('creates a link to the right folder with relative cwd', function(done) { + it('creates a link to the right folder with relative cwd', function (done) { var cwd = path.relative(process.cwd(), __dirname); var file = new File({ @@ -112,22 +119,25 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputPath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputPath, 'path should have changed'); - expect(files[0].symlink).toEqual(outputLink, 'symlink should be set'); - expect(files[0].isSymbolic()).toBe(true, 'file should be symbolic'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputPath); + expect(files[0].symlink).toEqual(outputLink); + expect(files[0].isSymbolic()).toBe(true); expect(outputLink).toEqual(inputPath); } - pipe([ - from.obj([file]), - vfs.symlink(outputRelative, { cwd: cwd }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputRelative, { cwd: cwd }), + concatArray(assert), + ], + done + ); }); - it('creates a link to the right folder with function and relative cwd', function(done) { + it('creates a link to the right folder with function and relative cwd', function (done) { var cwd = path.relative(process.cwd(), __dirname); var file = new File({ @@ -137,7 +147,6 @@ describe('symlink stream', function() { }); function outputFn(f) { - expect(f).toExist(); expect(f).toEqual(file); return outputRelative; } @@ -146,48 +155,46 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputPath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputPath, 'path should have changed'); - expect(files[0].symlink).toEqual(outputLink, 'symlink should be set'); - expect(files[0].isSymbolic()).toBe(true, 'file should be symbolic'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputPath); + expect(files[0].symlink).toEqual(outputLink); + expect(files[0].isSymbolic()).toBe(true); expect(outputLink).toEqual(inputPath); } - pipe([ - from.obj([file]), - vfs.symlink(outputFn, { cwd: cwd }), - concat(assert), - ], done); + pipeline( + [from([file]), vfs.symlink(outputFn, { cwd: cwd }), concatArray(assert)], + done + ); }); - it('creates a link for a file with buffered contents', function(done) { + it('creates a link for a file with buffered contents', function (done) { var file = new File({ base: inputBase, path: inputPath, - contents: new Buffer(contents), + contents: Buffer.from(contents), }); function assert(files) { var outputLink = fs.readlinkSync(outputPath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputPath, 'path should have changed'); - expect(files[0].symlink).toEqual(outputLink, 'symlink should be set'); - expect(files[0].isSymbolic()).toBe(true, 'file should be symbolic'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputPath); + expect(files[0].symlink).toEqual(outputLink); + expect(files[0].isSymbolic()).toBe(true); expect(outputLink).toEqual(inputPath); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase), - concat(assert), - ], done); + pipeline( + [from([file]), vfs.symlink(outputBase), concatArray(assert)], + done + ); }); - it('can create relative links', function(done) { + it('can create relative links', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -198,22 +205,25 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputPath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputPath, 'path should have changed'); - expect(files[0].symlink).toEqual(outputLink, 'symlink should be set'); - expect(files[0].isSymbolic()).toBe(true, 'file should be symbolic'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputPath); + expect(files[0].symlink).toEqual(outputLink); + expect(files[0].isSymbolic()).toBe(true); expect(outputLink).toEqual(path.normalize('../fixtures/test.txt')); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase, { relativeSymlinks: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputBase, { relativeSymlinks: true }), + concatArray(assert), + ], + done + ); }); - it('creates a link for a file with streaming contents', function(done) { + it('creates a link for a file with streaming contents', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -224,22 +234,21 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputPath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputPath, 'path should have changed'); - expect(files[0].symlink).toEqual(outputLink, 'symlink should be set'); - expect(files[0].isSymbolic()).toBe(true, 'file should be symbolic'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputPath); + expect(files[0].symlink).toEqual(outputLink); + expect(files[0].isSymbolic()).toBe(true); expect(outputLink).toEqual(inputPath); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase), - concat(assert), - ], done); + pipeline( + [from([file]), vfs.symlink(outputBase), concatArray(assert)], + done + ); }); - it('emits Vinyl objects that are symbolic', function(done) { + it('emits Vinyl objects that are symbolic', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -251,14 +260,13 @@ describe('symlink stream', function() { expect(files[0].isSymbolic()).toEqual(true); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase), - concat(assert), - ], done); + pipeline( + [from([file]), vfs.symlink(outputBase), concatArray(assert)], + done + ); }); - it('(*nix) creates a link for a directory', function(done) { + it('(*nix) creates a link for a directory', function (done) { if (isWindows) { this.skip(); return; @@ -279,23 +287,22 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputDirpath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputDirpath, 'path should have changed'); - expect(files[0].symlink).toEqual(outputLink, 'symlink should be set'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputDirpath); + expect(files[0].symlink).toEqual(outputLink); expect(outputLink).toEqual(inputDirpath); expect(stats.isDirectory()).toEqual(true); expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase), - concat(assert), - ], done); + pipeline( + [from([file]), vfs.symlink(outputBase), concatArray(assert)], + done + ); }); - it('(windows) creates a junction for a directory', function(done) { + it('(windows) creates a junction for a directory', function (done) { if (!isWindows) { this.skip(); return; @@ -316,24 +323,23 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputDirpath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputDirpath, 'path should have changed'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputDirpath); // When creating a junction, it seems Windows appends a separator - expect(files[0].symlink + path.sep).toEqual(outputLink, 'symlink should be set'); + expect(files[0].symlink + path.sep).toEqual(outputLink); expect(outputLink).toEqual(inputDirpath + path.sep); expect(stats.isDirectory()).toEqual(true); expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase), - concat(assert), - ], done); + pipeline( + [from([file]), vfs.symlink(outputBase), concatArray(assert)], + done + ); }); - it('(windows) options can disable junctions for a directory', function(done) { + it('(windows) options can disable junctions for a directory', function (done) { if (!isWindows) { this.skip(); return; @@ -354,23 +360,26 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputDirpath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputDirpath, 'path should have changed'); - expect(files[0].symlink).toEqual(outputLink, 'symlink should be set'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputDirpath); + expect(files[0].symlink).toEqual(outputLink); expect(outputLink).toEqual(inputDirpath); expect(stats.isDirectory()).toEqual(true); expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase, { useJunctions: false }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputBase, { useJunctions: false }), + concatArray(assert), + ], + done + ); }); - it('(windows) options can disable junctions for a directory (as a function)', function(done) { + it('(windows) options can disable junctions for a directory (as a function)', function (done) { if (!isWindows) { this.skip(); return; @@ -386,7 +395,6 @@ describe('symlink stream', function() { }); function useJunctions(f) { - expect(f).toExist(); expect(f).toBe(file); return false; } @@ -397,23 +405,26 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputDirpath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputDirpath, 'path should have changed'); - expect(files[0].symlink).toEqual(outputLink, 'symlink should be set'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputDirpath); + expect(files[0].symlink).toEqual(outputLink); expect(outputLink).toEqual(inputDirpath); expect(stats.isDirectory()).toEqual(true); expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase, { useJunctions: useJunctions }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputBase, { useJunctions: useJunctions }), + concatArray(assert), + ], + done + ); }); - it('(*nix) can create relative links for directories', function(done) { + it('(*nix) can create relative links for directories', function (done) { if (isWindows) { this.skip(); return; @@ -434,23 +445,26 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputDirpath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputDirpath, 'path should have changed'); - expect(files[0].symlink).toEqual(outputLink, 'symlink should be set'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputDirpath); + expect(files[0].symlink).toEqual(outputLink); expect(outputLink).toEqual(path.normalize('../fixtures/foo')); expect(stats.isDirectory()).toEqual(true); expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase, { relativeSymlinks: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputBase, { relativeSymlinks: true }), + concatArray(assert), + ], + done + ); }); - it('(windows) relativeSymlinks option is ignored when junctions are used', function(done) { + it('(windows) relativeSymlinks option is ignored when junctions are used', function (done) { if (!isWindows) { this.skip(); return; @@ -471,24 +485,30 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputDirpath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputDirpath, 'path should have changed'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputDirpath); // When creating a junction, it seems Windows appends a separator - expect(files[0].symlink + path.sep).toEqual(outputLink, 'symlink should be set'); + expect(files[0].symlink + path.sep).toEqual(outputLink); expect(outputLink).toEqual(inputDirpath + path.sep); expect(stats.isDirectory()).toEqual(true); expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase, { useJunctions: true, relativeSymlinks: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputBase, { + useJunctions: true, + relativeSymlinks: true, + }), + concatArray(assert), + ], + done + ); }); - it('(windows) supports relativeSymlinks option when link is not for a directory', function(done) { + it('(windows) supports relativeSymlinks option when link is not for a directory', function (done) { if (!isWindows) { this.skip(); return; @@ -504,21 +524,27 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputPath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputPath, 'path should have changed'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputPath); expect(outputLink).toEqual(path.normalize('../fixtures/test.txt')); } - pipe([ - from.obj([file]), - // The useJunctions option is ignored when file is not a directory - vfs.symlink(outputBase, { useJunctions: true, relativeSymlinks: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + // The useJunctions option is ignored when file is not a directory + vfs.symlink(outputBase, { + useJunctions: true, + relativeSymlinks: true, + }), + concatArray(assert), + ], + done + ); }); - it('(windows) can create relative links for directories when junctions are disabled', function(done) { + it('(windows) can create relative links for directories when junctions are disabled', function (done) { if (!isWindows) { this.skip(); return; @@ -539,23 +565,29 @@ describe('symlink stream', function() { var outputLink = fs.readlinkSync(outputDirpath); expect(files.length).toEqual(1); - expect(files).toInclude(file); - expect(files[0].base).toEqual(outputBase, 'base should have changed'); - expect(files[0].path).toEqual(outputDirpath, 'path should have changed'); - expect(files[0].symlink).toEqual(outputLink, 'symlink should be set'); + expect(files).toContain(file); + expect(files[0].base).toEqual(outputBase); + expect(files[0].path).toEqual(outputDirpath); + expect(files[0].symlink).toEqual(outputLink); expect(outputLink).toEqual(path.normalize('../fixtures/foo')); expect(stats.isDirectory()).toEqual(true); expect(lstats.isDirectory()).toEqual(false); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase, { useJunctions: false, relativeSymlinks: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputBase, { + useJunctions: false, + relativeSymlinks: true, + }), + concatArray(assert), + ], + done + ); }); - it('reports IO errors', function(done) { + it('reports IO errors', function (done) { // Changing the mode of a file is not supported by node.js in Windows. // This test is skipped on Windows because we have to chmod the file to 0. if (isWindows) { @@ -577,13 +609,10 @@ describe('symlink stream', function() { done(); } - pipe([ - from.obj([file]), - vfs.symlink(outputDirpath), - ], assert); + pipeline([from([file]), vfs.symlink(outputDirpath)], assert); }); - it('does not overwrite links with overwrite option set to false', function(done) { + it('does not overwrite links with overwrite option set to false', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ @@ -603,14 +632,17 @@ describe('symlink stream', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.symlink(outputBase, { overwrite: false }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputBase, { overwrite: false }), + concatArray(assert), + ], + done + ); }); - it('overwrites links with overwrite option set to true', function(done) { + it('overwrites links with overwrite option set to true', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ @@ -630,14 +662,17 @@ describe('symlink stream', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.symlink(outputBase, { overwrite: true }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputBase, { overwrite: true }), + concatArray(assert), + ], + done + ); }); - it('does not overwrite links with overwrite option set to a function that returns false', function(done) { + it('does not overwrite links with overwrite option set to a function that returns false', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ @@ -662,14 +697,17 @@ describe('symlink stream', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.symlink(outputBase, { overwrite: overwrite }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputBase, { overwrite: overwrite }), + concatArray(assert), + ], + done + ); }); - it('overwrites links with overwrite option set to a function that returns true', function(done) { + it('overwrites links with overwrite option set to a function that returns true', function (done) { var existingContents = 'Lorem Ipsum'; var file = new File({ @@ -694,17 +732,28 @@ describe('symlink stream', function() { fs.mkdirSync(outputBase); fs.writeFileSync(outputPath, existingContents); - pipe([ - from.obj([file]), - vfs.symlink(outputBase, { overwrite: overwrite }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputBase, { overwrite: overwrite }), + concatArray(assert), + ], + done + ); }); - it('emits an end event', function(done) { + it('emits an end event', function (done) { var symlinkStream = vfs.symlink(outputBase); - symlinkStream.on('end', done); + var ended = false; + function assert(err) { + expect(ended).toEqual(true); + done(err); + } + + symlinkStream.on('end', function () { + ended = true; + }); var file = new File({ base: inputBase, @@ -712,16 +761,21 @@ describe('symlink stream', function() { contents: null, }); - pipe([ - from.obj([file]), - symlinkStream, - ]); + pipeline([from([file]), symlinkStream], assert); }); - it('emits a finish event', function(done) { + it('emits a finish event', function (done) { var symlinkStream = vfs.symlink(outputBase); - symlinkStream.on('finish', done); + var finished = false; + symlinkStream.on('finish', function () { + finished = true; + }); + + function assert(err) { + expect(finished).toBeTruthy(); + done(err); + } var file = new File({ base: inputBase, @@ -729,43 +783,34 @@ describe('symlink stream', function() { contents: null, }); - pipe([ - from.obj([file]), - symlinkStream, - ]); + pipeline([from([file]), symlinkStream], assert); }); - it('errors when a non-Vinyl object is emitted', function(done) { + it('errors when a non-Vinyl object is emitted', function (done) { var file = {}; function assert(err) { - expect(err).toExist(); + expect(err).toEqual(expect.anything()); expect(err.message).toEqual('Received a non-Vinyl object in `symlink()`'); done(); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase), - ], assert); + pipeline([from([file]), vfs.symlink(outputBase)], assert); }); - it('errors when a buffer-mode stream is piped to it', function(done) { - var file = new Buffer('test'); + it('errors when a buffer-mode stream is piped to it', function (done) { + var file = Buffer.from('test'); function assert(err) { - expect(err).toExist(); + expect(err).toEqual(expect.anything()); expect(err.message).toEqual('Received a non-Vinyl object in `symlink()`'); done(); } - pipe([ - from([file]), - vfs.symlink(outputBase), - ], assert); + pipeline([from([file]), vfs.symlink(outputBase)], assert); }); - it('does not get clogged by highWaterMark', function(done) { + it('does not get clogged by highWaterMark', function (done) { var expectedCount = 17; var highwatermarkFiles = []; for (var idx = 0; idx < expectedCount; idx++) { @@ -777,17 +822,20 @@ describe('symlink stream', function() { highwatermarkFiles.push(file); } - pipe([ - from.obj(highwatermarkFiles), - count(expectedCount), - // Must be in the Writable position to test this - // So concat-stream cannot be used - vfs.symlink(outputBase), - ], done); + pipeline( + [ + from(highwatermarkFiles), + count(expectedCount), + // Must be in the Writable position to test this + // So concatArray stream cannot be used + vfs.symlink(outputBase), + ], + done + ); }); - it('allows backpressure when piped to another, slower stream', function(done) { - this.timeout(20000); + it('allows backpressure when piped to another, slower stream', function (done) { + this.timeout(0); var expectedCount = 24; var highwatermarkFiles = []; @@ -800,15 +848,18 @@ describe('symlink stream', function() { highwatermarkFiles.push(file); } - pipe([ - from.obj(highwatermarkFiles), - count(expectedCount), - vfs.symlink(outputBase), - slowCount(expectedCount), - ], done); + pipeline( + [ + from(highwatermarkFiles), + count(expectedCount), + vfs.symlink(outputBase), + slowCount(expectedCount), + ], + done + ); }); - it('respects readable listeners on symlink stream', function(done) { + it('respects readable listeners on symlink stream', function (done) { var file = new File({ base: inputBase, path: inputDirpath, @@ -818,7 +869,7 @@ describe('symlink stream', function() { var symlinkStream = vfs.symlink(outputBase); var readables = 0; - symlinkStream.on('readable', function() { + symlinkStream.on('readable', function () { var data = symlinkStream.read(); if (data != null) { @@ -831,13 +882,10 @@ describe('symlink stream', function() { done(err); } - pipe([ - from.obj([file]), - symlinkStream, - ], assert); + pipeline([from([file]), symlinkStream], assert); }); - it('respects data listeners on symlink stream', function(done) { + it('respects data listeners on symlink stream', function (done) { var file = new File({ base: inputBase, path: inputDirpath, @@ -847,7 +895,7 @@ describe('symlink stream', function() { var symlinkStream = vfs.symlink(outputBase); var datas = 0; - symlinkStream.on('data', function() { + symlinkStream.on('data', function () { datas++; }); @@ -856,13 +904,10 @@ describe('symlink stream', function() { done(err); } - pipe([ - from.obj([file]), - symlinkStream, - ], assert); + pipeline([from([file]), symlinkStream], assert); }); - it('sinks the stream if all the readable event handlers are removed', function(done) { + it('sinks the stream if all the readable event handlers are removed', function (done) { var expectedCount = 17; var highwatermarkFiles = []; for (var idx = 0; idx < expectedCount; idx++) { @@ -878,20 +923,23 @@ describe('symlink stream', function() { symlinkStream.on('readable', noop); - pipe([ - from.obj(highwatermarkFiles), - count(expectedCount), - // Must be in the Writable position to test this - // So concat-stream cannot be used - symlinkStream, - ], done); - - process.nextTick(function() { + pipeline( + [ + from(highwatermarkFiles), + count(expectedCount), + // Must be in the Writable position to test this + // So concatArray stream cannot be used + symlinkStream, + ], + done + ); + + process.nextTick(function () { symlinkStream.removeListener('readable', noop); }); }); - it('sinks the stream if all the data event handlers are removed', function(done) { + it('sinks the stream if all the data event handlers are removed', function (done) { var expectedCount = 17; var highwatermarkFiles = []; for (var idx = 0; idx < expectedCount; idx++) { @@ -907,20 +955,23 @@ describe('symlink stream', function() { symlinkStream.on('data', noop); - pipe([ - from.obj(highwatermarkFiles), - count(expectedCount), - // Must be in the Writable position to test this - // So concat-stream cannot be used - symlinkStream, - ], done); - - process.nextTick(function() { + pipeline( + [ + from(highwatermarkFiles), + count(expectedCount), + // Must be in the Writable position to test this + // So concatArray stream cannot be used + symlinkStream, + ], + done + ); + + process.nextTick(function () { symlinkStream.removeListener('data', noop); }); }); - it('does not pass options on to through2', function(done) { + it('does not pass options on to through2', function (done) { var file = new File({ base: inputBase, path: inputPath, @@ -928,21 +979,24 @@ describe('symlink stream', function() { }); // Reference: https://github.com/gulpjs/vinyl-fs/issues/153 - var read = expect.createSpy().andReturn(false); + var read = sinon.fake.returns(false); function assert() { // Called never because it's not a valid option - expect(read.calls.length).toEqual(0); + expect(read.called).toEqual(false); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase, { read: read }), - concat(assert), - ], done); + pipeline( + [ + from([file]), + vfs.symlink(outputBase, { read: read }), + concatArray(assert), + ], + done + ); }); - it('does not marshall a Vinyl object with isSymbolic method', function(done) { + it('does not marshall a Vinyl object with isSymbolic method', function (done) { var file = new File({ base: outputBase, path: outputPath, @@ -951,19 +1005,16 @@ describe('symlink stream', function() { function assert(files) { expect(files.length).toEqual(1); // Avoid comparing stats because they get reflected - delete files[0].stat; - expect(files[0]).toMatch(file); expect(files[0]).toBe(file); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase), - concat(assert), - ], done); + pipeline( + [from([file]), vfs.symlink(outputBase), concatArray(assert)], + done + ); }); - it('marshalls a Vinyl object without isSymbolic to a newer Vinyl', function(done) { + it('marshalls a Vinyl object without isSymbolic to a newer Vinyl', function (done) { var file = new File({ base: outputBase, path: outputPath, @@ -976,15 +1027,14 @@ describe('symlink stream', function() { function assert(files) { expect(files.length).toEqual(1); // Avoid comparing stats because they get reflected - delete files[0].stat; - expect(files[0]).toMatch(file); - expect(files[0]).toNotBe(file); + files[0].stat = file.stat; + expect(files[0]).toMatchObject(file); + expect(files[0]).not.toBe(file); } - pipe([ - from.obj([file]), - vfs.symlink(outputBase), - concat(assert), - ], done); + pipeline( + [from([file]), vfs.symlink(outputBase), concatArray(assert)], + done + ); }); }); diff --git a/test/utils/cleanup.js b/test/utils/cleanup.js index 740dfcbb..5189a539 100644 --- a/test/utils/cleanup.js +++ b/test/utils/cleanup.js @@ -1,13 +1,13 @@ 'use strict'; var rimraf = require('rimraf'); -var expect = require('expect'); +var sinon = require('sinon'); function cleanup(glob) { return function(cb) { - this.timeout(20000); + this.timeout(0); - expect.restoreSpies(); + sinon.restore(); if (!glob) { return cb(); diff --git a/test/utils/suite.js b/test/utils/suite.js new file mode 100644 index 00000000..3d6e8212 --- /dev/null +++ b/test/utils/suite.js @@ -0,0 +1,13 @@ +var streams = ['stream', 'streamx', 'readable-stream']; + +function describeStreams(name, suite) { + streams.forEach(function (moduleName) { + var stream = require(moduleName); + + describe(name + ' (using ' + moduleName + ')', function () { + suite(stream); + }); + }); +} + +module.exports = describeStreams; diff --git a/test/utils/test-constants.js b/test/utils/test-constants.js index 3d3099cc..7a9ddd67 100644 --- a/test/utils/test-constants.js +++ b/test/utils/test-constants.js @@ -29,7 +29,8 @@ var leBomInputPath = path.join(inputBase, './bom-utf16le.txt'); var bomContents = 'This file is saved as UTF-X with the appropriate BOM.\n'; var beNotBomInputPath = path.join(inputBase, './not-bom-utf16be.txt'); var leNotBomInputPath = path.join(inputBase, './not-bom-utf16le.txt'); -var notBomContents = 'This file is saved as UTF-16-X. It contains some garbage at the start that looks like a UTF-8-encoded BOM (but isn\'t).\n'; +var notBomContents = + "This file is saved as UTF-16-X. It contains some garbage at the start that looks like a UTF-8-encoded BOM (but isn't).\n"; var ranBomInputPath = path.join(inputBase, './ranbom.bin'); // Used for encoding tests var encodedInputPath = path.join(inputBase, './enc-gb2312.txt'); @@ -38,8 +39,14 @@ var encodedContents = '\u5b54\u5b50\u8bf4\u590d\u6d3b\u8282\u5f69\u86cb\n'; var symlinkNestedTarget = path.join(inputBase, './foo/bar/baz.txt'); var symlinkPath = path.join(outputBase, './test-symlink'); var symlinkDirpath = path.join(outputBase, './test-symlink-dir'); -var symlinkMultiDirpath = path.join(outputBase, './test-multi-layer-symlink-dir'); -var symlinkMultiDirpathSecond = path.join(outputBase, './test-multi-layer-symlink-dir2'); +var symlinkMultiDirpath = path.join( + outputBase, + './test-multi-layer-symlink-dir' +); +var symlinkMultiDirpathSecond = path.join( + outputBase, + './test-multi-layer-symlink-dir2' +); var symlinkNestedFirst = path.join(outputBase, './test-multi-layer-symlink'); var symlinkNestedSecond = path.join(outputBase, './foo/baz-link.txt'); // Paths that don't exist @@ -49,7 +56,8 @@ var neInputDirpath = path.join(neInputBase, './foo'); var neOutputDirpath = path.join(neOutputBase, './foo'); // Used for contents of files var contents = 'Hello World!\n'; -var sourcemapContents = '//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9maXh0dXJlcyIsIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzIjpbIi4vZml4dHVyZXMiXSwic291cmNlc0NvbnRlbnQiOlsiSGVsbG8gV29ybGQhXG4iXX0='; +var sourcemapContents = + '//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9maXh0dXJlcyIsIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzIjpbIi4vZml4dHVyZXMiXSwic291cmNlc0NvbnRlbnQiOlsiSGVsbG8gV29ybGQhXG4iXX0='; module.exports = { inputRelative: inputRelative, diff --git a/test/utils/test-streams.js b/test/utils/test-streams.js index 9c84ce9e..64b2d12b 100644 --- a/test/utils/test-streams.js +++ b/test/utils/test-streams.js @@ -1,75 +1,191 @@ 'use strict'; -var miss = require('mississippi'); var expect = require('expect'); -var to = miss.to; -var from = miss.from; -var through = miss.through; - -function string(length) { - return from(function(size, next) { - if (length <= 0) { - next(null, null); - return; - } - - var chunkSize = size <= length ? size : length; - - length -= size; - - var chunk = ''; - for (var x = 0; x < chunkSize; x++) { - chunk += 'a'; - } - - next(null, chunk); - }); -} - -function rename(filepath) { - return through.obj(function(file, enc, cb) { - file.path = filepath; - cb(null, file); - }); -} - -function includes(obj) { - return through.obj(function(file, enc, cb) { - expect(file).toInclude(obj); - cb(null, file); - }); -} - -function count(value) { - var count = 0; - return through.obj(function(file, enc, cb) { - count++; - cb(null, file); - }, function(cb) { - expect(count).toEqual(value); - cb(); - }); -} - -function slowCount(value) { - var count = 0; - return to.obj(function(file, enc, cb) { - count++; - - setTimeout(function() { - cb(null, file); - }, 250); - }, function(cb) { - expect(count).toEqual(value); - cb(); - }); -} - -module.exports = { - string: string, - rename: rename, - includes: includes, - count: count, - slowCount: slowCount, +module.exports = function makeUtils(stream) { + function chunks(length) { + var arr = new Array(length); + arr.fill('a'); + return stream.Readable.from(arr); + } + + function rename(filepath) { + return new stream.Transform({ + objectMode: true, + transform: function (file, enc, cb) { + if (typeof enc === 'function') { + cb = enc; + } + + file.path = filepath; + cb(null, file); + }, + }); + } + + function includes(obj) { + return new stream.Transform({ + objectMode: true, + transform: function (file, enc, cb) { + if (typeof enc === 'function') { + cb = enc; + } + + expect(file.path).toEqual(obj.path); + cb(null, file); + }, + }); + } + + function count(value) { + var count = 0; + return new stream.Transform({ + objectMode: true, + transform: function (file, enc, cb) { + if (typeof enc === 'function') { + cb = enc; + } + + count++; + cb(null, file); + }, + flush: function (cb) { + expect(count).toEqual(value); + cb(); + }, + }); + } + + function slowCount(value) { + var count = 0; + return new stream.Writable({ + objectMode: true, + write: function (file, enc, cb) { + if (typeof enc === 'function') { + cb = enc; + } + + count++; + + setTimeout(function () { + cb(null, file); + }, 250); + }, + end: function (data, enc, cb) { + expect(count).toEqual(value); + cb(); + }, + }); + } + + function concatString(fn, timeout) { + var collect = ''; + return new stream.Writable({ + objectMode: true, + write: function (chunk, enc, cb) { + if (typeof enc === 'function') { + cb = enc; + } + setTimeout(function () { + collect = collect + chunk; + cb(); + }, timeout || 1); + }, + final: function (cb) { + if (typeof fn === 'function') { + fn(collect); + } + + cb(); + }, + }); + } + + function concatBuffer(fn, timeout) { + var collect = Buffer.alloc(0); + return new stream.Writable({ + objectMode: true, + write: function (chunk, enc, cb) { + if (typeof enc === 'function') { + cb = enc; + } + setTimeout(function () { + collect = Buffer.concat([collect, chunk]); + cb(); + }, timeout || 1); + }, + final: function (cb) { + if (typeof fn === 'function') { + fn(collect); + } + + cb(); + }, + }); + } + + function concatArray(fn, timeout) { + var collect = []; + return new stream.Writable({ + objectMode: true, + write: function (chunk, enc, cb) { + if (typeof enc === 'function') { + cb = enc; + } + setTimeout(function () { + collect.push(chunk); + cb(); + }, timeout || 1); + }, + final: function (cb) { + if (typeof fn === 'function') { + fn(collect); + } + + cb(); + }, + }); + } + + function compareContents(comparator) { + return new stream.Transform({ + objectMode: true, + transform: function (file, enc, cb) { + if (typeof enc === 'function') { + cb = enc; + } + stream.pipeline( + [file.contents, concatBuffer(comparator)], + function (err) { + cb(err, file); + } + ); + }, + }); + } + + function fromError(error) { + return new stream.Readable({ + read: function (cb) { + if (typeof cb === 'function') { + cb(error); + } else { + this.destroy(error); + } + }, + }); + } + + return { + chunks: chunks, + rename: rename, + includes: includes, + count: count, + slowCount: slowCount, + concatString: concatString, + concatBuffer: concatBuffer, + concatArray: concatArray, + compareContents: compareContents, + fromError: fromError, + }; };