Skip to content

Commit

Permalink
chore: update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lukeed committed Jun 9, 2019
1 parent 195c3d5 commit 602641e
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 97 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
],
"devDependencies": {
"bundt": "^0.4.0",
"premove": "^1.0.0",
"tap-spec": "^5.0.0",
"tape": "^4.10.2"
}
Expand Down
240 changes: 143 additions & 97 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,139 +1,185 @@
'use strict';

const join = require('path').join;
const stats = require('fs').statSync;
const write = require('fs').writeFileSync;
const graceful = require('graceful-fs');
const Promise = require('bluebird');
const tempy = require('tempy');
const test = require('tape');
const premove = require('premove');
const { join, resolve } = require('path');
const { existsSync, statSync, writeFileSync } = require('fs');
const mkdirs = require('../dist');

const fn = require('../dist');
const isWin = process.platform === 'win32';

const co = Promise.coroutine;
const isDir = str => stats(str).isDirectory();
const getFixture = _ => join(tempy.directory(), 'foo/bar/baz');
const assertDir = (t, dir, mode) => {
mode = mode || 0o777 & (~process.umask());
(process.platform === 'win32') && (mode = 0o666);
t.is(stats(dir).mode & 0o777, mode);
t.true(isDir(dir));
test.Test.prototype.exists = function (str, bool, msg) {
msg = msg || (bool ? '~> (setup) exists' : '~> does not exist');
this.is(existsSync(str), bool, msg);
};

test('main', co(function * (t) {
const dir = getFixture();
const out = yield fn(dir);
t.true(out.length > 0);
assertDir(t, out);
t.end();
}));
test.Test.prototype.valid = function (dir, mode) {
let stats = statSync(dir);
mode = isWin ? 0o666 : (mode || 0o777 & (~process.umask()));
this.is(stats.mode & 0o777, mode, '~> correct mode');
this.true(stats.isDirectory(), '~> is a directory');
};

test('`fs` option', co(function * (t) {
const dir = getFixture();
yield fn(dir, { fs:graceful });
assertDir(t, dir);
test('exports', t => {
t.is(typeof mkdirs, 'function', 'a function');
t.end();
}));
});

test('single (relative)', async t => {
let out = await mkdirs('foo');
t.is(out, resolve('foo'), '~> returns the absolute file path');

test('`mode` option', co(function * (t) {
const mode = 0o744;
const dir = getFixture();
yield fn(dir, { mode });
assertDir(t, dir, mode);
t.exists(out, true, '~> filepath exists');
t.valid(out);

await premove(out);
t.exists(out, false, 'cleanup');

// Ensure it's writable
yield fn(dir);
assertDir(t, dir, mode);
t.end();
}));
});

test('single (absolute)', async t => {
let str = resolve('bar');
let out = await mkdirs(str);
t.is(out, str, '~> returns the absolute file path');

t.exists(out, true, '~> filepath exists');
t.valid(out);

await premove(out);
t.exists(out, false, 'cleanup');

test('dir exists', co(function * (t) {
const dir = yield fn(tempy.directory());
t.true(dir.length > 0);
assertDir(t, dir);
t.end();
}));
});

test('nested create / recursive', async t => {
let dir = resolve('./foo');

let out = await mkdirs('./foo/bar/baz');
t.exists(out, true, '~> filepath exists');
t.valid(out);

await premove(dir);
t.exists(dir, false, 'cleanup');

test('file exits', co(function * (t) {
const fp = tempy.file();
write(fp, '');
try {
yield fn(fp);
} catch (err) {
t.pass('throws');
t.is(err.code, 'EEXIST');
}
t.end();
}));
});

test('option: mode', async t => {
let mode = 0o744;
let out = await mkdirs('hello', { mode });

t.exists(out, true, '~> filepath exists');
t.valid(out, mode);

await premove(out);
t.exists(out, false, 'cleanup');

test('root dir', co(function * (t) {
const dir = yield fn('/');
t.true(dir.length > 0);
assertDir(t, dir);
t.end();
}));
});

test('option: cwd', async t => {
let dir = resolve('foobar');
let str = resolve('foobar/foo/bar');

let out = await mkdirs('foo/bar', { cwd:dir });
t.is(out, str, '~> returns the absolute file path');

t.exists(out, true, '~> filepath exists');
t.valid(out);

await premove(dir);
t.exists(dir, false, 'cleanup');

test('race two', co(function * (t) {
const dir = getFixture();
yield Promise.all([fn(dir), fn(dir)]);
assertDir(t, dir);
t.end();
}));
});

test('race many', co(function * (t) {
const dir = getFixture();
const all = [];
test('partially exists: directory', async t => {
let foo = resolve('foobar');
let dir = await mkdirs('foobar/baz');
let out = await mkdirs('hello/world', { cwd: dir });
let str = resolve('foobar/baz/hello/world');

for (let i = 0; i < 100; i++) {
all.push(fn(dir));
}
t.is(out, str, '~> returns the absolute file path');

t.exists(out, true, '~> filepath exists');
t.valid(out);

await premove(foo);
t.exists(foo, false, 'cleanup');

yield Promise.all(all);
assertDir(t, dir);
t.end();
}));
});

test('partially exists: file', async t => {
t.plan(9);

let foo = resolve('foobar');
let file = join(foo, 'bar');

let dir = await mkdirs(foo);
t.exists(dir, true, '~> (setup) dir exists');

// create "foobar/bar" as a file
writeFileSync(file, 'asd');
t.exists(file, true, '~> (setup) file exists');

test('handles null bytes in path', co(function * (t) {
const dir = join(tempy.directory(), 'foo\u0000bar');
try {
yield fn(dir);
await mkdirs('foobar/bar/hello');
} catch (err) {
t.pass('throws');
t.is(err.code, 'ENOENT');
t.true(/null bytes/.test(err.message));
t.true(err instanceof Error, 'throws Error');
t.is(err.message, 'ENOTDIR: not a directory', '~> message');
t.is(err.code, 'ENOTDIR', '~> code');
t.is(err.path, file, '~> path');
}
t.end();
}));

test('handles invalid path chars (win32)', co(function * (t) {
// We do this to please `nyc`
const platform = process.platform;
Object.defineProperty(process, 'platform', { value:'win32' });
t.exists('foobar/bar/hello', false, '~> did not create "hello" dir');
t.exists('foobar/bar', true, '~> file still remains');

await premove(foo);
t.exists(foo, false, 'cleanup');
});

test('path with null bytes', async t => {
t.plan(5);

const dir = join(tempy.directory(), 'foo"bar');
let dir = resolve('hello');
let str = resolve('hello/bar\u0000baz');

try {
yield fn(dir);
await mkdirs(str);
} catch (err) {
t.pass('throws');
t.is(err.code, 'EINVAL');
t.true(/invalid characters/.test(err.message));
t.true(err instanceof Error, 'throws Error');
t.is(err.code, 'ERR_INVALID_ARG_VALUE', '~> code');
t.true(err.message.includes('null bytes'), '~> message');
}

Object.defineProperty(process, 'platform', { value:platform });
t.end();
}));
t.exists(dir, true, '~> created "hello" base directory');

await premove(dir);
t.exists(dir, false, 'cleanup');
});

if (process.platform === 'win32') {
// We assume the `o:\` drive doesn't exist on Windows
test('handles non-existent root', co(function * (t) {
if (isWin) {
// assume the `o:\` drive doesn't exist on Windows
test('handles non-existent root', async t => {
try {
yield fn('o:\\foo');
await mkdirs('o:\\foo');
} catch (err) {
t.pass('throws');
t.is(err.code, 'ENOENT');
t.true(/no such file or directory/.test(err.message));
}
t.end();
}));
});

test('(windows) invalid pathname', async t => {
try {
t.plan(4);
await mkdirs('foo"bar');
} catch (err) {
t.true(err instanceof Error, 'throws Error');
t.is(err.message, 'EINVAL: invalid characters', '~> message');
t.is(err.path, 'foo"bar', '~> path');
t.is(err.code, 'EINVAL', '~> code');
}
});
}

0 comments on commit 602641e

Please sign in to comment.