From 602641e396f16c0f932a7c36210ecbc719901f2b Mon Sep 17 00:00:00 2001 From: Luke Edwards Date: Sun, 9 Jun 2019 11:29:30 -0700 Subject: [PATCH] chore: update tests --- package.json | 1 + test/index.js | 240 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 144 insertions(+), 97 deletions(-) diff --git a/package.json b/package.json index e40935a..5705060 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ ], "devDependencies": { "bundt": "^0.4.0", + "premove": "^1.0.0", "tap-spec": "^5.0.0", "tape": "^4.10.2" } diff --git a/test/index.js b/test/index.js index 60637f0..40ce146 100644 --- a/test/index.js +++ b/test/index.js @@ -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'); + } + }); }