diff --git a/gulp-util/index.d.ts b/gulp-util/index.d.ts
index feea14ec8e..1393fdfc3a 100644
--- a/gulp-util/index.d.ts
+++ b/gulp-util/index.d.ts
@@ -11,7 +11,7 @@ import vinyl = require('vinyl');
import chalk = require('chalk');
import through2 = require('through2');
-export class File extends vinyl { }
+export { vinyl as File };
/**
* Replaces a file extension in a path. Returns the new path.
diff --git a/vinyl/index.d.ts b/vinyl/index.d.ts
index ee3ae22bee..bfdb8e4bff 100644
--- a/vinyl/index.d.ts
+++ b/vinyl/index.d.ts
@@ -1,133 +1,327 @@
-// Type definitions for vinyl 1.2.0
+// Type definitions for vinyl 2.0.0
// Project: https://github.com/gulpjs/vinyl
-// Definitions by: vvakame , jedmao
+// Definitions by: vvakame , jedmao , Georgii Dolzhykov
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
///
+import * as fs from 'fs';
-
-import fs = require("fs");
-
-/**
- * A virtual file format.
- */
-declare class File {
- constructor(options?: {
-
- /**
- * Default: process.cwd()
- */
- cwd?: string;
-
- /**
- * Used for relative pathing. Typically where a glob starts.
- */
- base?: string;
-
- /**
- * Full path to the file.
- */
- path?: string;
-
- /**
- * Path history. Has no effect if options.path is passed.
- */
- history?: string[];
-
- /**
- * The result of an fs.stat call. See fs.Stats for more information.
- */
- stat?: fs.Stats;
-
- /**
- * File contents.
- * Type: Buffer, Stream, or null
- */
- contents?: Buffer | NodeJS.ReadWriteStream;
- });
+interface ConstructorOptions {
+ /**
+ * The current working directory of the file. Default: process.cwd()
+ */
+ cwd?: string;
/**
- * Default: process.cwd()
+ * Used for relative pathing. Typically where a glob starts. Default: options.cwd
*/
- public cwd: string;
-
- /**
- * Used for relative pathing. Typically where a glob starts.
- */
- public dirname: string;
- public basename: string;
- public base: string;
+ base?: string;
/**
* Full path to the file.
*/
- public path: string;
- public stat: fs.Stats;
+ path?: string;
/**
- * Gets and sets stem (filename without suffix) for the file path.
+ * Stores the path history. If `options.path` and `options.history` are both passed,
+ * `options.path` is appended to `options.history`. All `options.history` paths are
+ * normalized by the `file.path` setter.
+ * Default: `[]` (or `[options.path]` if `options.path` is passed)
*/
- public stem: string;
+ history?: string[];
/**
- * Gets and sets path.extname for the file path
+ * The result of an fs.stat call. This is how you mark the file as a directory or
+ * symbolic link. See `isDirectory()`, `isSymbolic()` and `fs.Stats` for more information.
+ * http://nodejs.org/api/fs.html#fs_class_fs_stats
*/
- public extname: string;
+ stat?: fs.Stats;
/**
- * Array of path values the file object has had
+ * File contents.
+ * Type: `Buffer`, `Stream`, or null
+ * Default: null
*/
- public history: string[];
+ contents?: Buffer | NodeJS.ReadableStream | null;
/**
- * Type: Buffer|Stream|null (Default: null)
+ * Any custom option properties will be directly assigned to the new Vinyl object.
*/
- public contents: Buffer | NodeJS.ReadableStream;
+ [customOption: string]: any;
+}
+
+interface FileConstructor {
+ new (options: ConstructorOptions & { contents: null }): NullFile;
+ new (options: ConstructorOptions & { contents: Buffer }): BufferFile;
+ new (options: ConstructorOptions & { contents: NodeJS.ReadableStream }): StreamFile;
+ new (options?: ConstructorOptions): File;
/**
- * Returns path.relative for the file base and file path.
+ * Checks if a given object is a vinyl file.
+ */
+ isVinyl(obj: any): obj is File;
+
+ /**
+ * Checks if a property is not managed internally.
+ */
+ isCustomProp(name: string): boolean;
+
+ prototype: File;
+}
+
+export = File;
+
+declare let File: FileConstructor;
+
+interface File {
+ /**
+ * Gets and sets the contents of the file. If set to a `Stream`, it is wrapped in
+ * a `cloneable-readable` stream.
+ *
+ * Throws when set to any value other than a `Stream`, a `Buffer` or `null`.
+ */
+ contents: Buffer | NodeJS.ReadableStream | null;
+
+ /**
+ * Gets and sets current working directory. Will always be normalized and have trailing
+ * separators removed.
+ *
+ * Throws when set to any value other than non-empty strings.
+ */
+ cwd: string;
+
+ //
+ /**
+ * Gets and sets base directory. Used for relative pathing (typically where a glob starts).
+ * When `null` or `undefined`, it simply proxies the `file.cwd` property. Will always be
+ * normalized and have trailing separators removed.
+ *
+ * Throws when set to any value other than non-empty strings or `null`/`undefined`.
+ *
+ * The setter's type is actually `string | null | undefined`, but TypeScript doesn't allow
+ * get/set accessors to be of different type. The property is declared as `string` for the
+ * compiler not to require useless null checks for the getter. (Hopefully, noone will need
+ * to assign `null` to this property.)
+ */
+ base: string;
+
+ /**
+ * Gets and sets the absolute pathname string or `undefined`. Setting to a different value
+ * appends the new path to `file.history`. If set to the same value as the current path, it
+ * is ignored. All new values are normalized and have trailing separators removed.
+ *
+ * Throws when set to any value other than a string.
+ *
+ * The getter is actually of type `string | undefined` whereas the setter is just `string`,
+ * however TypeScript doesn't allow get/set accessors to be of different type. See the
+ * comment for the `base` properties.
+ */
+ path: string;
+
+ /**
+ * Array of `file.path` values the Vinyl object has had, from `file.history[0]` (original)
+ * through `file.history[file.history.length - 1]` (current). `file.history` and its elements
+ * should normally be treated as read-only and only altered indirectly by setting `file.path`.
+ */
+ readonly history: ReadonlyArray;
+
+ /**
+ * Gets the result of `path.relative(file.base, file.path)`.
+ *
+ * Throws when set or when `file.path` is not set.
+ *
* Example:
- * var file = new File({
- * cwd: "/",
- * base: "/test/",
- * path: "/test/file.js"
- * });
- * console.log(file.relative); // file.js
+ *
+ * ```js
+ * var file = new File({
+ * cwd: '/',
+ * base: '/test/',
+ * path: '/test/file.js'
+ * });
+ *
+ * console.log(file.relative); // file.js
+ * ```
*/
- public relative: string;
+ relative: string;
/**
- * Returns true if file.contents is a Buffer.
+ * Gets and sets the dirname of `file.path`. Will always be normalized and have trailing
+ * separators removed.
+ *
+ * Throws when `file.path` is not set.
+ *
+ * Example:
+ *
+ * ```js
+ * var file = new File({
+ * cwd: '/',
+ * base: '/test/',
+ * path: '/test/file.js'
+ * });
+ *
+ * console.log(file.dirname); // /test
+ *
+ * file.dirname = '/specs';
+ *
+ * console.log(file.dirname); // /specs
+ * console.log(file.path); // /specs/file.js
+ * ```
*/
- public isBuffer(): boolean;
+ dirname: string;
/**
- * Returns true if file.contents is a Stream.
+ * Gets and sets the basename of `file.path`.
+ *
+ * Throws when `file.path` is not set.
+ *
+ * Example:
+ *
+ * ```js
+ * var file = new File({
+ * cwd: '/',
+ * base: '/test/',
+ * path: '/test/file.js'
+ * });
+ *
+ * console.log(file.basename); // file.js
+ *
+ * file.basename = 'file.txt';
+ *
+ * console.log(file.basename); // file.txt
+ * console.log(file.path); // /test/file.txt
+ * ```
*/
- public isStream(): boolean;
+ basename: string;
/**
- * Returns true if file.contents is null.
+ * Gets and sets stem (filename without suffix) of `file.path`.
+ *
+ * Throws when `file.path` is not set.
+ *
+ * Example:
+ *
+ * ```js
+ * var file = new File({
+ * cwd: '/',
+ * base: '/test/',
+ * path: '/test/file.js'
+ * });
+ *
+ * console.log(file.stem); // file
+ *
+ * file.stem = 'foo';
+ *
+ * console.log(file.stem); // foo
+ * console.log(file.path); // /test/foo.js
+ * ```
*/
- public isNull(): boolean;
+ stem: string;
/**
- * Returns true if this is a directory.
+ * Gets and sets extname of `file.path`.
+ *
+ * Throws when `file.path` is not set.
+ *
+ * Example:
+ *
+ * ```js
+ * var file = new File({
+ * cwd: '/',
+ * base: '/test/',
+ * path: '/test/file.js'
+ * });
+ *
+ * console.log(file.extname); // .js
+ *
+ * file.extname = '.txt';
+ *
+ * console.log(file.extname); // .txt
+ * console.log(file.path); // /test/file.txt
+ * ```
*/
- public isDirectory(): boolean;
+ extname: string;
/**
- * Returns a new File object with all attributes cloned. Custom attributes are deep-cloned.
+ * Gets and sets the path where the file points to if it's a symbolic link. Will always
+ * be normalized and have trailing separators removed.
+ *
+ * Throws when set to any value other than a string.
*/
- public clone(opts?: { contents?: boolean, deep?: boolean }): File;
+ symlink: string | null;
+
+ stat: fs.Stats | null;
+
+ [customProperty: string]: any;
/**
+ * Returns `true` if the file contents are a `Buffer`, otherwise `false`.
+ */
+ isBuffer(): this is BufferFile;
+
+ /**
+ * Returns `true` if the file contents are a `Stream`, otherwise `false`.
+ */
+ isStream(): this is StreamFile;
+
+ /**
+ * Returns `true` if the file contents are `null`, otherwise `false`.
+ */
+ isNull(): this is NullFile;
+
+ /**
+ * Returns `true` if the file represents a directory, otherwise `false`.
+ *
+ * A file is considered a directory when:
+ *
+ * - `file.isNull()` is `true`
+ * - `file.stat` is an object
+ * - `file.stat.isDirectory()` returns `true`
+ *
+ * When constructing a Vinyl object, pass in a valid `fs.Stats` object via `options.stat`.
+ * If you are mocking the `fs.Stats` object, you may need to stub the `isDirectory()` method.
+ */
+ isDirectory(): this is DirectoryFile;
+
+ /**
+ * Returns `true` if the file represents a symbolic link, otherwise `false`.
+ *
+ * A file is considered symbolic when:
+ *
+ * - `file.isNull()` is `true`
+ * - `file.stat` is an object
+ * - `file.stat.isSymbolicLink()` returns `true`
+ *
+ * When constructing a Vinyl object, pass in a valid `fs.Stats` object via `options.stat`.
+ * If you are mocking the `fs.Stats` object, you may need to stub the `isSymbolicLink()` method.
+ */
+ isSymbolic(): this is SymbolicFile;
+
+ /**
+ * Returns a new Vinyl object with all attributes cloned.
+ *
+ * __By default custom attributes are cloned deeply.__
+ *
+ * If `options` or `options.deep` is `false`, custom attributes will not be cloned deeply.
+ *
+ * If `file.contents` is a `Buffer` and `options.contents` is `false`, the `Buffer` reference
+ * will be reused instead of copied.
+ */
+ clone(opts?: { contents?: boolean, deep?: boolean } | boolean): this;
+
+ /**
+ * Returns a formatted-string interpretation of the Vinyl object.
+ * Automatically called by node's `console.log`.
+ */
+ inspect(): string;
+
+ /**
+ * @deprecated This method was removed in v2.0.
* If file.contents is a Buffer, it will write it to the stream.
* If file.contents is a Stream, it will pipe it to the stream.
* If file.contents is null, it will do nothing.
*/
- public pipe(
+ pipe(
stream: T,
opts?: {
/**
@@ -135,21 +329,43 @@ declare class File {
*/
end?: boolean;
}): T;
-
- /**
- * Returns a pretty String interpretation of the File. Useful for console.log.
- */
- public inspect(): string;
-
- /**
- * Checks if a given object is a vinyl file.
- */
- public static isVinyl(obj: any): boolean;
-
- /**
- * Checks if a property is not managed internally.
- */
- public static isCustomProp(name: string): boolean;
}
-export = File;
+// See https://github.com/Microsoft/TypeScript/issues/11796
+
+interface BufferFile extends File {
+ contents: Buffer;
+ isStream(): this is never;
+ isBuffer(): true;
+ isNull(): this is never;
+ isDirectory(): this is never;
+ isSymbolic(): this is never;
+}
+
+interface StreamFile extends File {
+ contents: NodeJS.ReadableStream;
+ isStream(): true;
+ isBuffer(): this is never;
+ isNull(): this is never;
+ isDirectory(): this is never;
+ isSymbolic(): this is never;
+}
+
+interface NullFile extends File {
+ contents: null;
+ isStream(): this is never;
+ isBuffer(): this is never;
+ isNull(): true;
+ isDirectory(): this is DirectoryFile;
+ isSymbolic(): this is SymbolicFile;
+}
+
+interface DirectoryFile extends NullFile {
+ isDirectory(): true;
+ isSymbolic(): this is never;
+}
+
+interface SymbolicFile extends NullFile {
+ isDirectory(): this is never;
+ isSymbolic(): true;
+}
diff --git a/vinyl/tsconfig.json b/vinyl/tsconfig.json
index a4a0b34380..27dd21e240 100644
--- a/vinyl/tsconfig.json
+++ b/vinyl/tsconfig.json
@@ -3,7 +3,7 @@
"module": "commonjs",
"target": "es6",
"noImplicitAny": true,
- "strictNullChecks": false,
+ "strictNullChecks": true,
"baseUrl": "../",
"typeRoots": [
"../"
@@ -16,4 +16,4 @@
"index.d.ts",
"vinyl-tests.ts"
]
-}
\ No newline at end of file
+}
diff --git a/vinyl/vinyl-tests.ts b/vinyl/vinyl-tests.ts
index 9d478b602e..b5c5dd9993 100644
--- a/vinyl/vinyl-tests.ts
+++ b/vinyl/vinyl-tests.ts
@@ -1,681 +1,1643 @@
///
///
+///
-import File = require('../vinyl');
-import Stream = require('stream');
-import fs = require('fs');
+'use strict';
-declare var fakeStream: NodeJS.ReadWriteStream;
+import * as fs from 'fs';
+import * as path from 'path';
+import expect from 'expect';
+var miss = require('mississippi');
+var cloneable = require('cloneable-readable');
-describe('File', () => {
+import File = require('vinyl');
- describe('constructor()', () => {
+/**
+ * Custom and private properties needed for tests.
+ *
+ * TODO:
+ * Is there a way to augment `File` (defined using `export =`) without introducing an extra
+ * interface and type assertions?
+ */
+interface TestFile extends File {
+ sourceMap?: any;
+ custom?: any;
+ _symlink?: string;
+ _contents?: Buffer | NodeJS.ReadableStream | null;
+ _cwd?: string;
+ _base?: string;
+}
- it('should default cwd to process.cwd', done => {
+declare module 'fs' {
+ class Stats { }
+}
+
+var pipe: (streams: [NodeJS.ReadableStream, NodeJS.WritableStream], cb: (err?: Error) => void) => void = miss.pipe;
+var from: (values: any[]) => NodeJS.ReadableStream = miss.from;
+var concat: (fn: (d: Buffer) => void) => NodeJS.WritableStream = miss.concat;
+var isCloneable: (obj: any) => boolean = cloneable.isCloneable;
+
+var isWin = (process.platform === 'win32');
+
+describe('File', function () {
+
+ describe('isVinyl()', function () {
+
+ it('returns true for a Vinyl object', function (done) {
var file = new File();
- file.cwd.should.equal(process.cwd());
+ var result = File.isVinyl(file);
+ expect(result).toEqual(true);
done();
});
- it('should default base to cwd', done => {
- var cwd = "/";
- var file = new File({cwd: cwd});
- file.basename.should.equal(cwd);
+ it('returns false for a normal object', function (done) {
+ var result = File.isVinyl({});
+ expect(result).toEqual(false);
done();
});
- it('should default base to cwd even when none is given', done => {
+ it('returns false for null', function (done) {
+ var result = File.isVinyl(null);
+ expect(result).toEqual(false);
+ done();
+ });
+
+ it('returns false for a string', function (done) {
+ var result = File.isVinyl('foobar');
+ expect(result).toEqual(false);
+ done();
+ });
+
+ it('returns false for a String object', function (done) {
+ var result = File.isVinyl(new String('foobar'));
+ expect(result).toEqual(false);
+ done();
+ });
+
+ it('returns false for a number', function (done) {
+ var result = File.isVinyl(1);
+ expect(result).toEqual(false);
+ done();
+ });
+
+ it('returns false for a Number object', function (done) {
+ var result = File.isVinyl(new Number(1));
+ expect(result).toEqual(false);
+ done();
+ });
+
+ // This is based on current implementation
+ // A test was added to document and make aware during internal changes
+ // TODO: decide if this should be leak-able
+ it('returns true for a mocked object', function (done) {
+ var result = File.isVinyl({ _isVinyl: true });
+ expect(result).toEqual(true);
+ done();
+ });
+ });
+
+ describe('defaults', function () {
+
+ it('defaults cwd to process.cwd', function (done) {
var file = new File();
- file.basename.should.equal(process.cwd());
+ expect(file.cwd).toEqual(process.cwd());
done();
});
- it('should default path to null', done => {
+ it('defaults base to process.cwd', function (done) {
var file = new File();
- should.not.exist(file.path);
+ expect(file.base).toEqual(process.cwd());
done();
});
- it('should default stat to null', done => {
+ it('defaults base to cwd property', function (done) {
+ var cwd = path.normalize('/');
+ var file = new File({ cwd: cwd });
+ expect(file.base).toEqual(cwd);
+ done();
+ });
+
+ it('defaults path to null', function (done) {
var file = new File();
- should.not.exist(file.stat);
+ expect(file.path).toNotExist();
+ expect(file.path).toEqual(null);
done();
});
- it('should default contents to null', done => {
+ it('defaults history to an empty array', function (done) {
var file = new File();
- should.not.exist(file.contents);
+ expect(file.history).toEqual([]);
done();
});
- it('should set base to given value', done => {
- var val = "/";
- var file = new File({base: val});
- file.basename.should.equal(val);
+ it('defaults stat to null', function (done) {
+ var file = new File();
+ expect(file.stat).toNotExist();
+ expect(file.stat).toEqual(null);
done();
});
- it('should set cwd to given value', done => {
- var val = "/";
- var file = new File({cwd: val});
- file.cwd.should.equal(val);
+ it('defaults contents to null', function (done) {
+ var file = new File();
+ expect(file.contents).toNotExist();
+ expect(file.contents).toEqual(null);
+ done();
+ });
+ });
+
+ describe('constructor()', function () {
+
+ it('sets base', function (done) {
+ var val = path.normalize('/');
+ var file = new File({ base: val });
+ expect(file.base).toEqual(val);
done();
});
- it('should set path to given value', done => {
- var val = "/test.coffee";
- var file = new File({path: val});
- file.path.should.equal(val);
+ it('sets cwd', function (done) {
+ var val = path.normalize('/');
+ var file = new File({ cwd: val });
+ expect(file.cwd).toEqual(val);
done();
});
- it('should set stat to given value', done => {
+ it('sets path (and history)', function (done) {
+ var val = path.normalize('/test.coffee');
+ var file = new File({ path: val });
+ expect(file.path).toEqual(val);
+ expect(file.history).toEqual([val]);
+ done();
+ });
+
+ it('sets history (and path)', function (done) {
+ var val = path.normalize('/test.coffee');
+ var file = new File({ history: [val] });
+ expect(file.path).toEqual(val);
+ expect(file.history).toEqual([val]);
+ done();
+ });
+
+ it('sets stat', function (done) {
var val = {};
- var file = new File({stat: val});
- file.stat.should.equal(val);
+ var file = new File({ stat: val as any as fs.Stats });
+ expect(file.stat).toEqual(val);
done();
});
- it('should set contents to given value', done => {
- var val = new Buffer("test");
- var file = new File({contents: val});
- file.contents.should.equal(val);
+ it('sets contents', function (done) {
+ var val = new Buffer('test');
+ var file = new File({ contents: val });
+ expect(file.contents).toEqual(val);
done();
});
- it('should default basename to cwd', done => {
- var cwd = "/";
- var file = new File({cwd: cwd});
- file.basename.should.equal(cwd);
+ it('sets custom properties', function (done) {
+ var sourceMap = {};
+ var file = new File({ sourceMap: sourceMap }) as TestFile;
+ expect(file.sourceMap).toEqual(sourceMap);
done();
});
- it('should default basename to cwd even when none is given', done => {
- var file = new File();
- file.basename.should.equal(process.cwd());
+ it('normalizes path', function (done) {
+ var val = '/test/foo/../test.coffee';
+ var expected = path.normalize(val);
+ var file = new File({ path: val });
+ expect(file.path).toEqual(expected);
+ expect(file.history).toEqual([expected]);
done();
});
- it('should set basename to given value', done => {
- var val = "/";
- var file = new File({base: val});
- file.basename.should.equal(val);
+ it('normalizes and removes trailing separator from path', function (done) {
+ var val = '/test/foo/../foo/';
+ var expected = path.normalize(val.slice(0, -1));
+ var file = new File({ path: val });
+ expect(file.path).toEqual(expected);
done();
});
- it('should default extname to null', done => {
- var cwd = "/";
- var file = new File({cwd: cwd});
- should.not.exist(file.path);
+ it('normalizes history', function (done) {
+ var val = [
+ '/test/bar/../bar/test.coffee',
+ '/test/foo/../test.coffee',
+ ];
+ var expected = val.map(function (p) {
+ return path.normalize(p);
+ });
+ var file = new File({ history: val });
+ expect(file.path).toEqual(expected[1]);
+ expect(file.history).toEqual(expected);
done();
});
- it('should default dirname to null', done => {
- var cwd = "/";
- var file = new File({cwd: cwd});
- should.not.exist(file.dirname);
+ it('normalizes and removes trailing separator from history', function (done) {
+ var val = [
+ '/test/foo/../foo/',
+ '/test/bar/../bar/',
+ ];
+ var expected = val.map(function (p) {
+ return path.normalize(p.slice(0, -1));
+ });
+ var file = new File({ history: val });
+ expect(file.history).toEqual(expected);
done();
});
- });
+ it('appends path to history if both exist and different from last', function (done) {
+ var val = path.normalize('/test/baz/test.coffee');
+ var history = [
+ path.normalize('/test/bar/test.coffee'),
+ path.normalize('/test/foo/test.coffee'),
+ ];
+ var file = new File({ path: val, history: history });
- describe('File.isVinyl()', () => {
- it('should return true when an object is a Vinyl file', done => {
- var file = new File();
- File.isVinyl(file).should.equal(true);
+ var expectedHistory = history.concat(val);
+
+ expect(file.path).toEqual(val);
+ expect(file.history).toEqual(expectedHistory);
done();
});
- it('should return false when an object is not a Vinyl file', done => {
- File.isVinyl({}).should.equal(false);
+ it('does not append path to history if both exist and same as last', function (done) {
+ var val = path.normalize('/test/baz/test.coffee');
+ var history = [
+ path.normalize('/test/bar/test.coffee'),
+ path.normalize('/test/foo/test.coffee'),
+ val,
+ ];
+ var file = new File({ path: val, history: history });
+
+ expect(file.path).toEqual(val);
+ expect(file.history).toEqual(history);
+ done();
+ });
+
+ it('does not mutate history array passed in', function (done) {
+ var val = path.normalize('/test/baz/test.coffee');
+ var history = [
+ path.normalize('/test/bar/test.coffee'),
+ path.normalize('/test/foo/test.coffee'),
+ ];
+ var historyCopy = Array.prototype.slice.call(history);
+ var file = new File({ path: val, history: history });
+
+ var expectedHistory = history.concat(val);
+
+ expect(file.path).toEqual(val);
+ expect(file.history).toEqual(expectedHistory);
+ expect(history).toEqual(historyCopy);
done();
});
});
- describe('File.isCustomProp()', () => {
- it('should return true when a File property is not managed internally', done => {
- File.isCustomProp('foobar').should.equal(true);
+ describe('isBuffer()', function () {
+
+ it('returns true when the contents are a Buffer', function (done) {
+ var val = new Buffer('test');
+ var file = new File({ contents: val });
+ expect(file.isBuffer()).toEqual(true);
done();
});
- it('should return false when a File property is managed internally', done => {
- File.isCustomProp('cwd').should.equal(false);
+ it('returns false when the contents are a Stream', function (done) {
+ var val = from([]);
+ var file = new File({ contents: val });
+ expect(file.isBuffer()).toEqual(false);
+ done();
+ });
+
+ it('returns false when the contents are null', function (done) {
+ var file = new File({ contents: null });
+ expect(file.isBuffer()).toEqual(false);
done();
});
});
- describe('isBuffer()', () => {
- it('should return true when the contents are a Buffer', done => {
- var val = new Buffer("test");
- var file = new File({contents: val});
- file.isBuffer().should.equal(true);
+ describe('isStream()', function () {
+
+ it('returns false when the contents are a Buffer', function (done) {
+ var val = new Buffer('test');
+ var file = new File({ contents: val });
+ expect(file.isStream()).toEqual(false);
done();
});
- it('should return false when the contents are a Stream', done => {
- var file = new File({ contents: fakeStream});
- file.isBuffer().should.equal(false);
+ it('returns true when the contents are a Stream', function (done) {
+ var val = from([]);
+ var file = new File({ contents: val });
+ expect(file.isStream()).toEqual(true);
done();
});
- it('should return false when the contents are a null', done => {
- var file = new File({contents: null});
- file.isBuffer().should.equal(false);
+ it('returns false when the contents are null', function (done) {
+ var file = new File({ contents: null });
+ expect(file.isStream()).toEqual(false);
done();
});
});
- describe('isStream()', () => {
- it('should return false when the contents are a Buffer', done => {
- var val = new Buffer("test");
- var file = new File({contents: val});
- file.isStream().should.equal(false);
+ describe('isNull()', function () {
+
+ it('returns false when the contents are a Buffer', function (done) {
+ var val = new Buffer('test');
+ var file = new File({ contents: val });
+ expect(file.isNull()).toEqual(false);
done();
});
- it('should return true when the contents are a Stream', done => {
- var file = new File({ contents: fakeStream});
- file.isStream().should.equal(true);
+ it('returns false when the contents are a Stream', function (done) {
+ var val = from([]);
+ var file = new File({ contents: val });
+ expect(file.isNull()).toEqual(false);
done();
});
- it('should return false when the contents are a null', done => {
- var file = new File({contents: null});
- file.isStream().should.equal(false);
+ it('returns true when the contents are null', function (done) {
+ var file = new File({ contents: null });
+ expect(file.isNull()).toEqual(true);
done();
});
});
- describe('isNull()', () => {
- it('should return false when the contents are a Buffer', done => {
- var val = new Buffer("test");
- var file = new File({contents: val});
- file.isNull().should.equal(false);
+ describe('isDirectory()', function () {
+ var fakeStat = {
+ isDirectory: function () {
+ return true;
+ },
+ } as any as fs.Stats;
+
+ it('returns false when the contents are a Buffer', function (done) {
+ var val = new Buffer('test');
+ var file = new File({ contents: val, stat: fakeStat });
+ expect(file.isDirectory()).toEqual(false);
done();
});
- it('should return false when the contents are a Stream', done => {
- var file = new File({ contents: fakeStream});
- file.isNull().should.equal(false);
+ it('returns false when the contents are a Stream', function (done) {
+ var val = from([]);
+ var file = new File({ contents: val, stat: fakeStat });
+ expect(file.isDirectory()).toEqual(false);
done();
});
- it('should return true when the contents are a null', done => {
- var file = new File({contents: null});
- file.isNull().should.equal(true);
+ it('returns true when the contents are null & stat.isDirectory is true', function (done) {
+ var file = new File({ contents: null, stat: fakeStat });
+ expect(file.isDirectory()).toEqual(true);
+ done();
+ });
+
+ it('returns false when stat exists but does not contain an isDirectory method', function (done) {
+ var file = new File({ contents: null, stat: {} as any as fs.Stats });
+ expect(file.isDirectory()).toEqual(false);
+ done();
+ });
+
+ it('returns false when stat does not exist', function (done) {
+ var file = new File({ contents: null });
+ expect(file.isDirectory()).toEqual(false);
done();
});
});
- describe('clone()', () => {
- it('should copy all attributes over with Buffer', done => {
+ describe('isSymbolic()', function () {
+ var fakeStat = {
+ isSymbolicLink: function () {
+ return true;
+ },
+ } as any as fs.Stats;
+
+ it('returns false when the contents are a Buffer', function (done) {
+ var val = new Buffer('test');
+ var file = new File({ contents: val, stat: fakeStat });
+ expect(file.isSymbolic()).toEqual(false);
+ done();
+ });
+
+ it('returns false when the contents are a Stream', function (done) {
+ var val = from([]);
+ var file = new File({ contents: val, stat: fakeStat });
+ expect(file.isSymbolic()).toEqual(false);
+ done();
+ });
+
+ it('returns true when the contents are null & stat.isSymbolicLink is true', function (done) {
+ var file = new File({ contents: null, stat: fakeStat });
+ expect(file.isSymbolic()).toEqual(true);
+ done();
+ });
+
+ it('returns false when stat exists but does not contain an isSymbolicLink method', function (done) {
+ var file = new File({ contents: null, stat: {} as any as fs.Stats });
+ expect(file.isSymbolic()).toEqual(false);
+ done();
+ });
+
+ it('returns false when stat does not exist', function (done) {
+ var file = new File({ contents: null });
+ expect(file.isSymbolic()).toEqual(false);
+ done();
+ });
+ });
+
+ describe('clone()', function () {
+
+ it('copies all attributes over with Buffer contents', function (done) {
var options = {
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: new Buffer("test")
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ contents: new Buffer('test'),
};
var file = new File(options);
var file2 = file.clone();
- file2.should.not.equal(file, 'refs should be different');
- file2.cwd.should.equal(file.cwd);
- file2.basename.should.equal(file.basename);
- file2.path.should.equal(file.path);
-
- let fileContents = file.contents;
- let file2Contents = file2.contents;
-
- file2Contents.should.not.equal(fileContents, 'buffer ref should be different');
-
- let fileUtf8Contents = fileContents instanceof Buffer ?
- fileContents.toString('utf8') :
- (fileContents).toString();
- let file2Utf8Contents = file2Contents instanceof Buffer ?
- file2Contents.toString('utf8') :
- (file2Contents).toString();
-
- file2Utf8Contents.should.equal(fileUtf8Contents);
+ expect(file2).toNotBe(file);
+ expect(file2.cwd).toEqual(file.cwd);
+ expect(file2.base).toEqual(file.base);
+ expect(file2.path).toEqual(file.path);
+ expect(file2.contents).toNotBe(file.contents);
+ expect(file2.contents.toString('utf8')).toEqual(file.contents.toString('utf8'));
done();
});
- it('should copy all attributes over with Stream', done => {
+ it('assigns Buffer content reference when contents option is false', function (done) {
var options = {
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: fakeStream
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.js',
+ contents: new Buffer('test'),
+ };
+ var file = new File(options);
+
+ var copy1 = file.clone({ contents: false });
+ expect(copy1.contents).toBe(file.contents);
+
+ var copy2 = file.clone();
+ expect(copy2.contents).toNotBe(file.contents);
+
+ // TypeScript: expected compilation error
+ //var copy3 = file.clone({ contents: 'invalid' });
+ //expect(copy3.contents).toNotBe(file.contents);
+ //done();
+ });
+
+ it('copies all attributes over with Stream contents', function (done) {
+ var options = {
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ contents: from(['wa', 'dup']),
};
var file = new File(options);
var file2 = file.clone();
- file2.should.not.equal(file, 'refs should be different');
- file2.cwd.should.equal(file.cwd);
- file2.basename.should.equal(file.basename);
- file2.path.should.equal(file.path);
- file2.contents.should.equal(file.contents, 'stream ref should be the same');
- done();
+ expect(file2).toNotBe(file);
+ expect(file2.cwd).toEqual(file.cwd);
+ expect(file2.base).toEqual(file.base);
+ expect(file2.path).toEqual(file.path);
+ expect(file2.contents).toNotBe(file.contents);
+
+ var ends = 2;
+ var data: Buffer;
+ var data2: Buffer;
+
+ function assert(err: any) {
+ if (err) {
+ done(err);
+ return;
+ }
+
+ if (--ends === 0) {
+ expect(data).toNotBe(data2);
+ expect(data.toString('utf8')).toEqual(data2.toString('utf8'));
+ done();
+ }
+ }
+
+ pipe([
+ file.contents,
+ concat(function (d) {
+ data = d;
+ }),
+ ], assert);
+
+ pipe([
+ file2.contents,
+ concat(function (d) {
+ data2 = d;
+ }),
+ ], assert);
});
- it('should copy all attributes over with null', done => {
+ it('does not start flowing until all clones flows (data)', function (done) {
var options = {
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: fakeStream
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ contents: from(['wa', 'dup']),
+ };
+ var file = new File(options);
+ var file2 = file.clone();
+ var ends = 2;
+
+ var data = '';
+ var data2 = '';
+
+ function assert() {
+ if (--ends === 0) {
+ expect(data).toEqual(data2);
+ done();
+ }
+ }
+
+ // Start flowing file2
+ file2.contents.on('data', function (chunk: Buffer) {
+ data2 += chunk.toString('utf8');
+ });
+
+ process.nextTick(function () {
+ // Nothing was written yet
+ expect(data).toEqual('');
+ expect(data2).toEqual('');
+
+ // Starts flowing file
+ file.contents.on('data', function (chunk: Buffer) {
+ data += chunk.toString('utf8');
+ });
+ });
+
+ file2.contents.on('end', assert);
+ file.contents.on('end', assert);
+ });
+
+ it('does not start flowing until all clones flows (readable)', function (done) {
+ var options = {
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ contents: from(['wa', 'dup']),
};
var file = new File(options);
var file2 = file.clone();
- file2.should.not.equal(file, 'refs should be different');
- file2.cwd.should.equal(file.cwd);
- file2.basename.should.equal(file.basename);
- file2.path.should.equal(file.path);
- should.not.exist(file2.contents);
+ var data2 = '';
+
+ function assert(data: Buffer) {
+ expect(data.toString('utf8')).toEqual(data2);
+ }
+
+ // Start flowing file2
+ file2.contents.on('readable', function (this: NodeJS.ReadableStream) {
+ var chunk: string | Buffer;
+ while ((chunk = this.read()) !== null) {
+ data2 += chunk.toString();
+ }
+ });
+
+ pipe([
+ file.contents,
+ concat(assert),
+ ], done);
+ });
+
+ it('copies all attributes over with null contents', function (done) {
+ var options = {
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ contents: null,
+ };
+ var file = new File(options);
+ var file2 = file.clone();
+
+ expect(file2).toNotBe(file);
+ expect(file2.cwd).toEqual(file.cwd);
+ expect(file2.base).toEqual(file.base);
+ expect(file2.path).toEqual(file.path);
+ expect(file2.contents).toNotExist();
done();
});
- it('should properly clone the `stat` property', done => {
+ it('properly clones the `stat` property', function (done) {
var options = {
- cwd: "/",
- base: "/test/",
- path: "/test/test.js",
- contents: new Buffer("test"),
- stat: fs.statSync(__filename)
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.js',
+ contents: new Buffer('test'),
+ stat: fs.statSync(__filename),
};
var file = new File(options);
var copy = file.clone();
- // ReSharper disable WrongExpressionStatement
- copy.stat.isFile().should.be.true;
- // ReSharper restore WrongExpressionStatement
+ expect(copy.stat).toExist();
+ if (copy.stat != null) {
+ expect(copy.stat.isFile()).toEqual(true);
+ expect(copy.stat.isDirectory()).toEqual(false);
+ expect(file.stat).toBeAn(fs.Stats);
+ expect(copy.stat).toBeAn(fs.Stats);
+ }
+ done();
+ });
+
+ it('properly clones the `history` property', function (done) {
+ var options = {
+ cwd: path.normalize('/'),
+ base: path.normalize('/test/'),
+ path: path.normalize('/test/test.js'),
+ contents: new Buffer('test'),
+ };
+
+ var file = new File(options);
+ var copy = file.clone();
+
+ expect(copy.history[0]).toEqual(options.path);
+ copy.path = 'lol';
+ expect(file.path).toNotEqual(copy.path);
+ done();
+ });
+
+ it('copies custom properties', function (done) {
+ var options = {
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ contents: null,
+ custom: { meta: {} },
+ };
+
+ var file = new File(options) as TestFile;
+ var file2 = file.clone();
+
+ expect(file2).toNotBe(file);
+ expect(file2.cwd).toEqual(file.cwd);
+ expect(file2.base).toEqual(file.base);
+ expect(file2.path).toEqual(file.path);
+ expect(file2.custom).toNotBe(file.custom);
+ expect(file2.custom.meta).toNotBe(file.custom.meta);
+ expect(file2.custom).toEqual(file.custom);
+ done();
+ });
+
+ it('copies history', function (done) {
+ var options = {
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ contents: null,
+ };
+ var history = [
+ path.normalize('/test/test.coffee'),
+ path.normalize('/test/test.js'),
+ path.normalize('/test/test-938di2s.js'),
+ ];
+
+ var file = new File(options);
+ file.path = history[1];
+ file.path = history[2];
+ var file2 = file.clone();
+
+ expect(file2.history).toEqual(history);
+ expect(file2.history).toNotBe(file.history);
+ expect(file2.path).toEqual(history[2]);
+ done();
+ });
+
+ it('supports deep & shallow copy of all attributes', function (done) {
+ var options = {
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ contents: null,
+ custom: { meta: {} },
+ };
+
+ var file = new File(options) as TestFile;
+
+ var file2 = file.clone();
+ expect(file2.custom).toEqual(file.custom);
+ expect(file2.custom).toNotBe(file.custom);
+ expect(file2.custom.meta).toEqual(file.custom.meta);
+ expect(file2.custom.meta).toNotBe(file.custom.meta);
+
+ var file3 = file.clone(true);
+ expect(file3.custom).toEqual(file.custom);
+ expect(file3.custom).toNotBe(file.custom);
+ expect(file3.custom.meta).toEqual(file.custom.meta);
+ expect(file3.custom.meta).toNotBe(file.custom.meta);
+
+ var file4 = file.clone({ deep: true });
+ expect(file4.custom).toEqual(file.custom);
+ expect(file4.custom).toNotBe(file.custom);
+ expect(file4.custom.meta).toEqual(file.custom.meta);
+ expect(file4.custom.meta).toNotBe(file.custom.meta);
+
+ var file5 = file.clone(false);
+ expect(file5.custom).toEqual(file.custom);
+ expect(file5.custom).toBe(file.custom);
+ expect(file5.custom.meta).toEqual(file.custom.meta);
+ expect(file5.custom.meta).toBe(file.custom.meta);
+
+ var file6 = file.clone({ deep: false });
+ expect(file6.custom).toEqual(file.custom);
+ expect(file6.custom).toBe(file.custom);
+ expect(file6.custom.meta).toEqual(file.custom.meta);
+ expect(file6.custom.meta).toBe(file.custom.meta);
done();
});
+
+ // TypeScript: known issue
+ // Compilation error: "Base constructors must all have the same return type."
+ // it('supports inheritance', function (done) {
+ // class ExtendedFile extends File { }
+ // var file = new ExtendedFile();
+ // var file2 = file.clone();
+
+ // expect(file2).toNotBe(file);
+ // expect(file2.constructor).toBe(ExtendedFile);
+ // expect(file2).toBeAn(ExtendedFile);
+ // expect(file2).toBeA(File);
+ // expect(ExtendedFile.prototype.isPrototypeOf(file2)).toEqual(true);
+ // expect(File.prototype.isPrototypeOf(file2)).toEqual(true);
+ // done();
+ // });
});
- describe('pipe()', () => {
- it('should write to stream with Buffer', done => {
- var options = {
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: new Buffer("test")
- };
- var file = new File(options);
- var stream = new Stream.PassThrough();
- stream.on('data', (chunk: any) => {
- should.exist(chunk);
- (chunk instanceof Buffer).should.equal(true, 'should write as a buffer');
- chunk.toString('utf8').should.equal(options.contents.toString('utf8'));
- });
- stream.on('end', () => {
- done();
- });
- var ret = file.pipe(stream);
- ret.should.equal(stream, 'should return the stream');
- });
+ describe('inspect()', function () {
- it('should pipe to stream with Stream', done => {
- var testChunk = new Buffer("test");
- var options = {
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: new Stream.PassThrough()
- };
- var file = new File(options);
- var stream = new Stream.PassThrough();
- stream.on('data', (chunk: any) => {
- should.exist(chunk);
- (chunk instanceof Buffer).should.equal(true, 'should write as a buffer');
- chunk.toString('utf8').should.equal(testChunk.toString('utf8'));
- done();
- });
- var ret = file.pipe(stream);
- ret.should.equal(stream, 'should return the stream');
-
- let fileContents = file.contents;
- if (fileContents instanceof Buffer) {
- fileContents.write(testChunk.toString());
- }
- });
-
- it('should do nothing with null', done => {
- var options = {
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: fakeStream
- };
- var file = new File(options);
- var stream = new Stream.PassThrough();
- stream.on('data', () => {
- throw new Error("should not write");
- });
- stream.on('end', () => {
- done();
- });
- var ret = file.pipe(stream);
- ret.should.equal(stream, 'should return the stream');
- });
-
- it('should write to stream with Buffer', done => {
- var options = {
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: new Buffer("test")
- };
- var file = new File(options);
- var stream = new Stream.PassThrough();
- stream.on('data', (chunk: any) => {
- should.exist(chunk);
- (chunk instanceof Buffer).should.equal(true, 'should write as a buffer');
- chunk.toString('utf8').should.equal(options.contents.toString('utf8'));
- done();
- });
- stream.on('end', () => {
- throw new Error("should not end");
- });
- var ret = file.pipe(stream, {end: false});
- ret.should.equal(stream, 'should return the stream');
- });
-
- it('should pipe to stream with Stream', done => {
- var testChunk = new Buffer("test");
- var options = {
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: new Stream.PassThrough()
- };
- var file = new File(options);
- var stream = new Stream.PassThrough();
- stream.on('data', (chunk: any) => {
- should.exist(chunk);
- (chunk instanceof Buffer).should.equal(true, 'should write as a buffer');
- chunk.toString('utf8').should.equal(testChunk.toString('utf8'));
- done();
- });
- stream.on('end', () => {
- throw new Error("should not end");
- });
- var ret = file.pipe(stream, {end: false});
- ret.should.equal(stream, 'should return the stream');
-
- let fileContents = file.contents;
- if (fileContents instanceof Buffer) {
- fileContents.write(testChunk.toString());
- }
- });
-
- it('should do nothing with null', done => {
- var options = {
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: fakeStream
- };
- var file = new File(options);
- var stream = new Stream.PassThrough();
- stream.on('data', () => {
- throw new Error("should not write");
- });
- stream.on('end', () => {
- throw new Error("should not end");
- });
- var ret = file.pipe(stream, {end: false});
- ret.should.equal(stream, 'should return the stream');
- process.nextTick(done);
- });
- });
-
- describe('inspect()', () => {
- it('should return correct format when no contents and no path', done => {
+ it('returns correct format when no contents and no path', function (done) {
var file = new File();
- file.inspect().should.equal('');
+ expect(file.inspect()).toEqual('');
done();
});
- it('should return correct format when Buffer and no path', done => {
- var val = new Buffer("test");
- var file = new File({
- contents: val
- });
- file.inspect().should.equal('>');
+ it('returns correct format when Buffer contents and no path', function (done) {
+ var val = new Buffer('test');
+ var file = new File({ contents: val });
+ expect(file.inspect()).toEqual('>');
done();
});
- it('should return correct format when Buffer and relative path', done => {
- var val = new Buffer("test");
+ it('returns correct format when Buffer contents and relative path', function (done) {
+ var val = new Buffer('test');
var file = new File({
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: val
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ contents: val,
});
- file.inspect().should.equal('>');
+ expect(file.inspect()).toEqual('>');
done();
});
- it('should return correct format when Buffer and only path and no base', done => {
- var val = new Buffer("test");
+ it('returns correct format when Stream contents and relative path', function (done) {
var file = new File({
- cwd: "/",
- path: "/test/test.coffee",
- contents: val
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ contents: from([]),
});
- delete file.basename;
- file.inspect().should.equal('>');
+ expect(file.inspect()).toEqual('>');
done();
});
- it('should return correct format when Stream and relative path', done => {
+ it('returns correct format when null contents and relative path', function (done) {
var file = new File({
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: new Stream.PassThrough()
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ contents: null,
});
- file.inspect().should.equal('>');
- done();
- });
-
- it('should return correct format when null and relative path', done => {
- var file = new File({
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee",
- contents: null
- });
- file.inspect().should.equal('');
+ expect(file.inspect()).toEqual('');
done();
});
});
- describe('contents get/set', () => {
- it('should work with Buffer', done => {
- var val = new Buffer("test");
+ describe('contents get/set', function () {
+
+ it('returns _contents', function (done) {
+ var val = new Buffer('test');
+ var file = new File() as TestFile;
+ file._contents = val;
+ expect(file.contents).toEqual(val);
+ done();
+ });
+
+ it('sets _contents', function (done) {
+ var val = new Buffer('test');
+ var file = new File() as TestFile;
+ file.contents = val;
+ expect(file._contents).toEqual(val);
+ done();
+ });
+
+ it('sets a Buffer', function (done) {
+ var val = new Buffer('test');
var file = new File();
file.contents = val;
- file.contents.should.equal(val);
+ expect(file.contents).toEqual(val);
done();
});
- it('should work with Stream', done => {
- var val = new Stream.PassThrough();
+ it('wraps Stream in Cloneable', function (done) {
+ var val = from([]);
var file = new File();
file.contents = val;
- file.contents.should.equal(val);
+ expect(isCloneable(file.contents)).toEqual(true);
done();
});
- it('should work with null', done => {
+ it('does not double wrap a Cloneable', function (done) {
+ var val = from([]);
+ var clone = cloneable(val);
var file = new File();
- file.contents = null;
- (file.contents === null).should.equal(true);
+ file.contents = clone;
+ expect((file.contents as any)._original).toBe(val);
done();
});
- it('should not work with string', done => {
- var val = "test";
+ it('sets null', function (done) {
+ var val = null;
var file = new File();
- try {
- file.contents = new Buffer(val);
- } catch (err) {
- should.exist(err);
- done();
+ file.contents = val;
+ expect(file.contents).toEqual(null);
+ done();
+ });
+
+ // TypeScript: expected compilation error
+ // it('does not set a string', function (done) {
+ // var val = 'test';
+ // var file = new File();
+ // function invalid() {
+ // file.contents = val;
+ // }
+ // expect(invalid).toThrow();
+ // done();
+ // });
+ });
+
+ describe('cwd get/set', function () {
+
+ it('returns _cwd', function (done) {
+ var val = '/test';
+ var file = new File() as TestFile;
+ file._cwd = val;
+ expect(file.cwd).toEqual(val);
+ done();
+ });
+
+ it('sets _cwd', function (done) {
+ var val = '/test';
+ var file = new File() as TestFile;
+ file.cwd = val;
+ expect(file._cwd).toEqual(path.normalize(val));
+ done();
+ });
+
+ it('normalizes and removes trailing separator on set', function (done) {
+ var val = '/test/foo/../foo/';
+ var expected = path.normalize(val.slice(0, -1));
+ var file = new File();
+
+ file.cwd = val;
+
+ expect(file.cwd).toEqual(expected);
+
+ var val2 = '\\test\\foo\\..\\foo\\';
+ var expected2 = path.normalize(isWin ? val2.slice(0, -1) : val2);
+
+ file.cwd = val2;
+
+ expect(file.cwd).toEqual(expected2);
+ done();
+ });
+
+ // TypeScript: expected compilation error
+ // it('throws on set with invalid values', function (done) {
+ // var invalidValues = [
+ // '',
+ // null,
+ // undefined,
+ // true,
+ // false,
+ // 0,
+ // Infinity,
+ // NaN,
+ // {},
+ // [],
+ // ];
+ // var file = new File();
+
+ // invalidValues.forEach(function (val) {
+ // function invalid() {
+ // file.cwd = val;
+ // }
+ // expect(invalid).toThrow('cwd must be a non-empty string.');
+ // });
+
+ // done();
+ // });
+ });
+
+ describe('base get/set', function () {
+
+ it('proxies cwd when omitted', function (done) {
+ var file = new File({ cwd: '/test' });
+ expect(file.base).toEqual(file.cwd);
+ done();
+ });
+
+ it('proxies cwd when same', function (done) {
+ var file = new File({
+ cwd: '/test',
+ base: '/test',
+ });
+ file.cwd = '/foo/';
+ expect(file.base).toEqual(file.cwd);
+
+ var file2 = new File({
+ cwd: '/test',
+ });
+ file2.base = '/test/';
+ file2.cwd = '/foo/';
+ expect(file2.base).toEqual(file.cwd);
+ done();
+ });
+
+ // TypeScript: known issue, see the comment for the `base` property.
+ // it('proxies to cwd when null or undefined', function (done) {
+ // var file = new File({
+ // cwd: '/foo',
+ // base: '/bar',
+ // });
+ // expect(file.base).toNotEqual(file.cwd);
+ // file.base = null;
+ // expect(file.base).toEqual(file.cwd);
+ // file.base = '/bar/';
+ // expect(file.base).toNotEqual(file.cwd);
+ // file.base = undefined;
+ // expect(file.base).toEqual(file.cwd);
+ // done();
+ // });
+
+ it('returns _base', function (done) {
+ var val = '/test/';
+ var file = new File() as TestFile;
+ file._base = val;
+ expect(file.base).toEqual(val);
+ done();
+ });
+
+ it('sets _base', function (done) {
+ var val = '/test/foo';
+ var file = new File() as TestFile;
+ file.base = val;
+ expect(file._base).toEqual(path.normalize(val));
+ done();
+ });
+
+ it('normalizes and removes trailing separator on set', function (done) {
+ var val = '/test/foo/../foo/';
+ var expected = path.normalize(val.slice(0, -1));
+ var file = new File();
+
+ file.base = val;
+
+ expect(file.base).toEqual(expected);
+
+ var val2 = '\\test\\foo\\..\\foo\\';
+ var expected2 = path.normalize(isWin ? val2.slice(0, -1) : val2);
+
+ file.base = val2;
+
+ expect(file.base).toEqual(expected2);
+ done();
+ });
+
+ // TypeScript: expected compilation error
+ // it('throws on set with invalid values', function (done) {
+ // var invalidValues = [
+ // true,
+ // false,
+ // 1,
+ // 0,
+ // Infinity,
+ // NaN,
+ // '',
+ // {},
+ // [],
+ // ];
+ // var file = new File();
+
+ // invalidValues.forEach(function (val) {
+ // function invalid() {
+ // file.base = val;
+ // }
+ // expect(invalid).toThrow('base must be a non-empty string, or null/undefined.');
+ // });
+
+ // done();
+ // });
+ });
+
+ describe('relative get/set', function () {
+
+ it('throws on set', function (done) {
+ var file = new File();
+
+ function invalid() {
+ file.relative = 'test';
}
- });
- });
- describe('relative get/set', () => {
- it('should error on set', done => {
+ expect(invalid).toThrow('File.relative is generated from the base and path attributes. Do not modify it.');
+ done();
+ });
+
+ it('throws on get with no path', function (done) {
var file = new File();
- try {
- file.relative = "test";
- } catch (err) {
- should.exist(err);
- done();
+
+ function invalid() {
+ file.relative;
}
+
+ expect(invalid).toThrow('No path specified! Can not get relative.');
+ done();
});
- it('should error on get when no base', done => {
- var a: string;
+ it('returns a relative path from base', function (done) {
+ var file = new File({
+ base: '/test/',
+ path: '/test/test.coffee',
+ });
+
+ expect(file.relative).toEqual('test.coffee');
+ done();
+ });
+
+ it('returns a relative path from cwd', function (done) {
+ var file = new File({
+ cwd: '/',
+ path: '/test/test.coffee',
+ });
+
+ expect(file.relative).toEqual(path.normalize('test/test.coffee'));
+ done();
+ });
+
+ it('does not append separator when directory', function (done) {
+ var file = new File({
+ base: '/test',
+ path: '/test/foo/bar',
+ stat: {
+ isDirectory: function () {
+ return true;
+ },
+ } as any as fs.Stats,
+ });
+
+ expect(file.relative).toEqual(path.normalize('foo/bar'));
+ done();
+ });
+
+ it('does not append separator when symlink', function (done) {
+ var file = new File({
+ base: '/test',
+ path: '/test/foo/bar',
+ stat: {
+ isSymbolicLink: function () {
+ return true;
+ },
+ } as any as fs.Stats,
+ });
+
+ expect(file.relative).toEqual(path.normalize('foo/bar'));
+ done();
+ });
+
+ it('does not append separator when directory & symlink', function (done) {
+ var file = new File({
+ base: '/test',
+ path: '/test/foo/bar',
+ stat: {
+ isDirectory: function () {
+ return true;
+ },
+ isSymbolicLink: function () {
+ return true;
+ },
+ } as any as fs.Stats,
+ });
+
+ expect(file.relative).toEqual(path.normalize('foo/bar'));
+ done();
+ });
+ });
+
+ describe('dirname get/set', function () {
+
+ it('throws on get with no path', function (done) {
var file = new File();
- delete file.basename;
- try {
- // ReSharper disable once AssignedValueIsNeverUsed
- a = file.relative;
- } catch (err) {
- should.exist(err);
- done();
+
+ function invalid() {
+ file.dirname;
}
+
+ expect(invalid).toThrow('No path specified! Can not get dirname.');
+ done();
});
- it('should error on get when no path', done => {
- var a: string;
+ it('returns the dirname without trailing separator', function (done) {
+ var file = new File({
+ cwd: '/',
+ base: '/test',
+ path: '/test/test.coffee',
+ });
+
+ expect(file.dirname).toEqual(path.normalize('/test'));
+ done();
+ });
+
+ it('throws on set with no path', function (done) {
var file = new File();
- try {
- // ReSharper disable once AssignedValueIsNeverUsed
- a = file.relative;
- } catch (err) {
- should.exist(err);
- done();
+
+ function invalid() {
+ file.dirname = '/test';
}
- });
- it('should return a relative path from base', done => {
- var file = new File({
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee"
- });
- file.relative.should.equal("test.coffee");
+ expect(invalid).toThrow('No path specified! Can not set dirname.');
done();
});
- it('should return a relative path from cwd', done => {
+ it('replaces the dirname of the path', function (done) {
var file = new File({
- cwd: "/",
- path: "/test/test.coffee"
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
});
- file.relative.should.equal("test/test.coffee");
+
+ file.dirname = '/test/foo';
+ expect(file.path).toEqual(path.normalize('/test/foo/test.coffee'));
done();
});
});
- describe('path get/set', () => {
+ describe('basename get/set', function () {
- it('should return an absolute path', done => {
- var file = new File({
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee"
- });
- file.path.should.equal("/test/test.coffee");
- done();
- });
-
- });
-
- describe('history get', () => {
- it('should error on set', done => {
+ it('throws on get with no path', function (done) {
var file = new File();
- try {
- file.history = [];
- } catch (err) {
- should.exist(err);
- done();
+
+ function invalid() {
+ return file.basename;
}
+
+ expect(invalid).toThrow('No path specified! Can not get basename.');
+ done();
});
- it('should return an history', done => {
+ it('returns the basename of the path', function (done) {
var file = new File({
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee"
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
});
- file.history.should.equal(["/test/test.coffee"]);
+
+ expect(file.basename).toEqual('test.coffee');
done();
});
- });
-
- describe('dirname get', () => {
-
- it('should return an dirname', done => {
+ it('does not append trailing separator when directory', function (done) {
var file = new File({
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee"
+ path: '/test/foo',
+ stat: {
+ isDirectory: function () {
+ return true;
+ },
+ } as any as fs.Stats,
});
- file.dirname.should.equal("test");
+
+ expect(file.basename).toEqual('foo');
done();
});
- it('should set dirname to given value', done => {
- var file = new File();
- file.dirname = ".ext"
- file.dirname.should.equal(".ext")
+ it('does not append trailing separator when symlink', function (done) {
+ var file = new File({
+ path: '/test/foo',
+ stat: {
+ isSymbolicLink: function () {
+ return true;
+ },
+ } as any as fs.Stats,
+ });
+
+ expect(file.basename).toEqual('foo');
done();
});
- it('should set dirname to null', done => {
+ it('does not append trailing separator when directory & symlink', function (done) {
+ var file = new File({
+ path: '/test/foo',
+ stat: {
+ isDirectory: function () {
+ return true;
+ },
+ isSymbolicLink: function () {
+ return true;
+ },
+ } as any as fs.Stats,
+ });
+
+ expect(file.basename).toEqual('foo');
+ done();
+ });
+
+ it('removes trailing separator', function (done) {
+ var file = new File({
+ path: '/test/foo/',
+ });
+
+ expect(file.basename).toEqual('foo');
+ done();
+ });
+
+ it('removes trailing separator when directory', function (done) {
+ var file = new File({
+ path: '/test/foo/',
+ stat: {
+ isDirectory: function () {
+ return true;
+ },
+ } as any as fs.Stats,
+ });
+
+ expect(file.basename).toEqual('foo');
+ done();
+ });
+
+ it('removes trailing separator when symlink', function (done) {
+ var file = new File({
+ path: '/test/foo/',
+ stat: {
+ isSymbolicLink: function () {
+ return true;
+ },
+ } as any as fs.Stats,
+ });
+
+ expect(file.basename).toEqual('foo');
+ done();
+ });
+
+ it('removes trailing separator when directory & symlink', function (done) {
+ var file = new File({
+ path: '/test/foo/',
+ stat: {
+ isDirectory: function () {
+ return true;
+ },
+ isSymbolicLink: function () {
+ return true;
+ },
+ } as any as fs.Stats,
+ });
+
+ expect(file.basename).toEqual('foo');
+ done();
+ });
+
+ it('throws on set with no path', function (done) {
var file = new File();
- file.dirname = null
- should.not.exist(file.dirname)
+
+ function invalid() {
+ file.basename = 'test.coffee';
+ }
+
+ expect(invalid).toThrow('No path specified! Can not set basename.');
+ done();
+ });
+
+ it('replaces the basename of the path', function (done) {
+ var file = new File({
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ });
+
+ file.basename = 'foo.png';
+ expect(file.path).toEqual(path.normalize('/test/foo.png'));
done();
});
});
- describe('extname get/set', () => {
+ describe('stem get/set', function () {
- it('should return an extname', done => {
+ it('throws on get with no path', function (done) {
+ var file = new File();
+
+ function invalid() {
+ file.stem;
+ }
+
+ expect(invalid).toThrow('No path specified! Can not get stem.');
+ done();
+ });
+
+ it('returns the stem of the path', function (done) {
var file = new File({
- cwd: "/",
- base: "/test/",
- path: "/test/test.coffee"
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
});
- file.dirname.should.equal(".coffee");
+
+ expect(file.stem).toEqual('test');
done();
});
- it('should set extname to given value', done => {
+ it('throws on set with no path', function (done) {
var file = new File();
- file.extname = ".ext"
- file.extname.should.equal(".ext")
+
+ function invalid() {
+ file.stem = 'test.coffee';
+ }
+
+ expect(invalid).toThrow('No path specified! Can not set stem.');
done();
});
- it('should set extname to null', done => {
- var file = new File();
- file.extname = null
- should.not.exist(file.extname)
+ it('replaces the stem of the path', function (done) {
+ var file = new File({
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ });
+
+ file.stem = 'foo';
+ expect(file.path).toEqual(path.normalize('/test/foo.coffee'));
done();
});
});
+ describe('extname get/set', function () {
+
+ it('throws on get with no path', function (done) {
+ var file = new File();
+
+ function invalid() {
+ file.extname;
+ }
+
+ expect(invalid).toThrow('No path specified! Can not get extname.');
+ done();
+ });
+
+ it('returns the extname of the path', function (done) {
+ var file = new File({
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ });
+
+ expect(file.extname).toEqual('.coffee');
+ done();
+ });
+
+ it('throws on set with no path', function (done) {
+ var file = new File();
+
+ function invalid() {
+ file.extname = '.coffee';
+ }
+
+ expect(invalid).toThrow('No path specified! Can not set extname.');
+ done();
+ });
+
+ it('replaces the extname of the path', function (done) {
+ var file = new File({
+ cwd: '/',
+ base: '/test/',
+ path: '/test/test.coffee',
+ });
+
+ file.extname = '.png';
+ expect(file.path).toEqual(path.normalize('/test/test.png'));
+ done();
+ });
+ });
+
+ describe('path get/set', function () {
+
+ it('records path in history upon instantiation', function (done) {
+ var file = new File({
+ cwd: '/',
+ path: '/test/test.coffee',
+ });
+ var history = [
+ path.normalize('/test/test.coffee'),
+ ];
+
+ expect(file.path).toEqual(history[0]);
+ expect(file.history).toEqual(history);
+ done();
+ });
+
+ it('records path in history when set', function (done) {
+ var val = path.normalize('/test/test.js');
+ var file = new File({
+ cwd: '/',
+ path: '/test/test.coffee',
+ });
+ var history = [
+ path.normalize('/test/test.coffee'),
+ val,
+ ];
+
+ file.path = val;
+ expect(file.path).toEqual(val);
+ expect(file.history).toEqual(history);
+
+ var val2 = path.normalize('/test/test.es6');
+ history.push(val2);
+
+ file.path = val2;
+ expect(file.path).toEqual(val2);
+ expect(file.history).toEqual(history);
+ done();
+ });
+
+ it('does not record path in history when set to the current path', function (done) {
+ var val = path.normalize('/test/test.coffee');
+ var file = new File({
+ cwd: '/',
+ path: val,
+ });
+ var history = [
+ val,
+ ];
+
+ file.path = val;
+ file.path = val;
+ expect(file.path).toEqual(val);
+ expect(file.history).toEqual(history);
+ done();
+ });
+
+ it('does not record path in history when set to empty string', function (done) {
+ var val = path.normalize('/test/test.coffee');
+ var file = new File({
+ cwd: '/',
+ path: val,
+ });
+ var history = [
+ val,
+ ];
+
+ file.path = '';
+ expect(file.path).toEqual(val);
+ expect(file.history).toEqual(history);
+ done();
+ });
+
+ // TypeScript: known issue, see the comment for the `base` property.
+ // it('throws on set with null path', function(done) {
+ // var file = new File();
+
+ // expect(file.path).toNotExist();
+ // expect(file.history).toEqual([]);
+
+ // function invalid() {
+ // file.path = null;
+ // }
+
+ // expect(invalid).toThrow('path should be a string.');
+ // done();
+ // });
+
+ it('normalizes the path upon set', function (done) {
+ var val = '/test/foo/../test.coffee';
+ var expected = path.normalize(val);
+ var file = new File();
+
+ file.path = val;
+
+ expect(file.path).toEqual(expected);
+ expect(file.history).toEqual([expected]);
+ done();
+ });
+
+ it('removes the trailing separator upon set', function (done) {
+ var file = new File();
+ file.path = '/test/';
+
+ expect(file.path).toEqual(path.normalize('/test'));
+ expect(file.history).toEqual([path.normalize('/test')]);
+ done();
+ });
+
+ it('removes the trailing separator upon set when directory', function (done) {
+ var file = new File({
+ stat: {
+ isDirectory: function () {
+ return true;
+ },
+ } as any as fs.Stats,
+ });
+ file.path = '/test/';
+
+ expect(file.path).toEqual(path.normalize('/test'));
+ expect(file.history).toEqual([path.normalize('/test')]);
+ done();
+ });
+
+ it('removes the trailing separator upon set when symlink', function (done) {
+ var file = new File({
+ stat: {
+ isSymbolicLink: function () {
+ return true;
+ },
+ } as any as fs.Stats,
+ });
+ file.path = '/test/';
+
+ expect(file.path).toEqual(path.normalize('/test'));
+ expect(file.history).toEqual([path.normalize('/test')]);
+ done();
+ });
+
+ it('removes the trailing separator upon set when directory & symlink', function (done) {
+ var file = new File({
+ stat: {
+ isDirectory: function () {
+ return true;
+ },
+ isSymbolicLink: function () {
+ return true;
+ },
+ } as any as fs.Stats,
+ });
+ file.path = '/test/';
+
+ expect(file.path).toEqual(path.normalize('/test'));
+ expect(file.history).toEqual([path.normalize('/test')]);
+ done();
+ });
+ });
+
+ describe('symlink get/set', function () {
+
+ it('return null on get with no symlink', function (done) {
+ var file = new File();
+
+ expect(file.symlink).toEqual(null);
+ done();
+ });
+
+ it('returns _symlink', function (done) {
+ var val = '/test/test.coffee';
+ var file = new File() as TestFile;
+ file._symlink = val;
+
+ expect(file.symlink).toEqual(val);
+ done();
+ });
+
+ it('throws on set with non-string', function (done) {
+ var file = new File();
+
+ function invalid() {
+ file.symlink = null;
+ }
+
+ expect(invalid).toThrow('symlink should be a string');
+ done();
+ });
+
+ it('sets _symlink', function (done) {
+ var val = '/test/test.coffee';
+ var expected = path.normalize(val);
+ var file = new File() as TestFile;
+ file.symlink = val;
+
+ expect(file._symlink).toEqual(expected);
+ done();
+ });
+
+ it('allows relative symlink', function (done) {
+ var val = 'test.coffee';
+ var file = new File();
+ file.symlink = val;
+
+ expect(file.symlink).toEqual(val);
+ done();
+ });
+
+ it('normalizes and removes trailing separator upon set', function (done) {
+ var val = '/test/foo/../bar/';
+ var expected = path.normalize(val.slice(0, -1));
+ var file = new File();
+ file.symlink = val;
+
+ expect(file.symlink).toEqual(expected);
+ done();
+ });
+ });
});