Repository: jprichardson/node-fs-extra
Pull request #880 (2021-04-01 20:01:19)

copy*(): Error when unknown file type is encountered
Replaces & closes #812

Implements suggestions in https://github.com/jprichardson/node-fs-extra/pull/812#pullrequestreview-432759032; since that PR was abandoned without updates.


Patch:
diff --git a/lib/copy-sync/copy-sync.js b/lib/copy-sync/copy-sync.js
index 72174de..2d9523e 100644
--- a/lib/copy-sync/copy-sync.js
+++ b/lib/copy-sync/copy-sync.js
@@ -21,7 +21,7 @@ function copySync (src, dest, opts) {
     see https://github.com/jprichardson/node-fs-extra/issues/269`)
   }
 
-  const { srcStat, destStat } = stat.checkPathsSync(src, dest, 'copy')
+  const { srcStat, destStat } = stat.checkPathsSync(src, dest, 'copy', opts)
   stat.checkParentPathsSync(src, srcStat, dest, 'copy')
   return handleFilterAndCopy(destStat, src, dest, opts)
 }
@@ -47,6 +47,9 @@ function getStats (destStat, src, dest, opts) {
            srcStat.isCharacterDevice() ||
            srcStat.isBlockDevice()) return onFile(srcStat, destStat, src, dest, opts)
   else if (srcStat.isSymbolicLink()) return onLink(destStat, src, dest, opts)
+  else if (srcStat.isSocket()) throw new Error(`Cannot copy a socket file: ${src}`)
+  else if (srcStat.isFIFO()) throw new Error(`Cannot copy a FIFO pipe: ${src}`)
+  throw new Error(`Unknown file: ${src}`)
 }
 
 function onFile (srcStat, destStat, src, dest, opts) {
@@ -98,13 +101,8 @@ function setDestTimestamps (src, dest) {
 }
 
 function onDir (srcStat, destStat, src, dest, opts) {
-  if (destStat) {
-    if (destStat.isDirectory()) {
-      return copyDir(src, dest, opts)
-    }
-    throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)
-  }
-  return mkDirAndCopy(srcStat.mode, src, dest, opts)
+  if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts)
+  return copyDir(src, dest, opts)
 }
 
 function mkDirAndCopy (srcMode, src, dest, opts) {
@@ -120,7 +118,7 @@ function copyDir (src, dest, opts) {
 function copyDirItem (item, src, dest, opts) {
   const srcItem = path.join(src, item)
   const destItem = path.join(dest, item)
-  const { destStat } = stat.checkPathsSync(srcItem, destItem, 'copy')
+  const { destStat } = stat.checkPathsSync(srcItem, destItem, 'copy', opts)
   return startCopy(destStat, srcItem, destItem, opts)
 }
 
diff --git a/lib/copy/copy.js b/lib/copy/copy.js
index 480dfbb..c12578d 100644
--- a/lib/copy/copy.js
+++ b/lib/copy/copy.js
@@ -27,7 +27,7 @@ function copy (src, dest, opts, cb) {
     see https://github.com/jprichardson/node-fs-extra/issues/269`)
   }
 
-  stat.checkPaths(src, dest, 'copy', (err, stats) => {
+  stat.checkPaths(src, dest, 'copy', opts, (err, stats) => {
     if (err) return cb(err)
     const { srcStat, destStat } = stats
     stat.checkParentPaths(src, srcStat, dest, 'copy', err => {
@@ -72,6 +72,9 @@ function getStats (destStat, src, dest, opts, cb) {
              srcStat.isCharacterDevice() ||
              srcStat.isBlockDevice()) return onFile(srcStat, destStat, src, dest, opts, cb)
     else if (srcStat.isSymbolicLink()) return onLink(destStat, src, dest, opts, cb)
+    else if (srcStat.isSocket()) return cb(new Error(`Cannot copy a socket file: ${src}`))
+    else if (srcStat.isFIFO()) return cb(new Error(`Cannot copy a FIFO pipe: ${src}`))
+    return cb(new Error(`Unknown file: ${src}`))
   })
 }
 
@@ -142,13 +145,8 @@ function setDestTimestamps (src, dest, cb) {
 }
 
 function onDir (srcStat, destStat, src, dest, opts, cb) {
-  if (destStat) {
-    if (destStat.isDirectory()) {
-      return copyDir(src, dest, opts, cb)
-    }
-    return cb(new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`))
-  }
-  return mkDirAndCopy(srcStat.mode, src, dest, opts, cb)
+  if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts, cb)
+  return copyDir(src, dest, opts, cb)
 }
 
 function mkDirAndCopy (srcMode, src, dest, opts, cb) {
@@ -177,7 +175,7 @@ function copyDirItems (items, src, dest, opts, cb) {
 function copyDirItem (items, item, src, dest, opts, cb) {
   const srcItem = path.join(src, item)
   const destItem = path.join(dest, item)
-  stat.checkPaths(srcItem, destItem, 'copy', (err, stats) => {
+  stat.checkPaths(srcItem, destItem, 'copy', opts, (err, stats) => {
     if (err) return cb(err)
     const { destStat } = stats
     startCopy(destStat, srcItem, destItem, opts, err => {
diff --git a/lib/ensure/link.js b/lib/ensure/link.js
index 2cd4196..f6d6748 100644
--- a/lib/ensure/link.js
+++ b/lib/ensure/link.js
@@ -5,6 +5,7 @@ const path = require('path')
 const fs = require('graceful-fs')
 const mkdir = require('../mkdirs')
 const pathExists = require('../path-exists').pathExists
+const { areIdentical } = require('../util/stat')
 
 function createLink (srcpath, dstpath, callback) {
   function makeLink (srcpath, dstpath) {
@@ -14,14 +15,13 @@ function createLink (srcpath, dstpath, callback) {
     })
   }
 
-  pathExists(dstpath, (err, destinationExists) => {
-    if (err) return callback(err)
-    if (destinationExists) return callback(null)
-    fs.lstat(srcpath, (err) => {
+  fs.lstat(dstpath, (_, dstStat) => {
+    fs.lstat(srcpath, (err, srcStat) => {
       if (err) {
         err.message = err.message.replace('lstat', 'ensureLink')
         return callback(err)
       }
+      if (dstStat && areIdentical(srcStat, dstStat)) return callback(null)
 
       const dir = path.dirname(dstpath)
       pathExists(dir, (err, dirExists) => {
@@ -37,11 +37,14 @@ function createLink (srcpath, dstpath, callback) {
 }
 
 function createLinkSync (srcpath, dstpath) {
-  const destinationExists = fs.existsSync(dstpath)
-  if (destinationExists) return undefined
+  let dstStat
+  try {
+    dstStat = fs.lstatSync(dstpath)
+  } catch {}
 
   try {
-    fs.lstatSync(srcpath)
+    const srcStat = fs.lstatSync(srcpath)
+    if (dstStat && areIdentical(srcStat, dstStat)) return
   } catch (err) {
     err.message = err.message.replace('lstat', 'ensureLink')
     throw err
diff --git a/lib/ensure/symlink.js b/lib/ensure/symlink.js
index fe68b79..2b93052 100644
--- a/lib/ensure/symlink.js
+++ b/lib/ensure/symlink.js
@@ -2,7 +2,7 @@
 
 const u = require('universalify').fromCallback
 const path = require('path')
-const fs = require('graceful-fs')
+const fs = require('../fs')
 const _mkdirs = require('../mkdirs')
 const mkdirs = _mkdirs.mkdirs
 const mkdirsSync = _mkdirs.mkdirsSync
@@ -17,26 +17,38 @@ const symlinkTypeSync = _symlinkType.symlinkTypeSync
 
 const pathExists = require('../path-exists').pathExists
 
+const { areIdentical } = require('../util/stat')
+
 function createSymlink (srcpath, dstpath, type, callback) {
   callback = (typeof type === 'function') ? type : callback
   type = (typeof type === 'function') ? false : type
 
-  pathExists(dstpath, (err, destinationExists) => {
+  fs.lstat(dstpath, (err, stats) => {
+    if (!err && stats.isSymbolicLink()) {
+      Promise.all([
+        fs.stat(srcpath),
+        fs.stat(dstpath)
+      ]).then(([srcStat, dstStat]) => {
+        if (areIdentical(srcStat, dstStat)) return callback(null)
+        _createSymlink(srcpath, dstpath, type, callback)
+      })
+    } else _createSymlink(srcpath, dstpath, type, callback)
+  })
+}
+
+function _createSymlink (srcpath, dstpath, type, callback) {
+  symlinkPaths(srcpath, dstpath, (err, relative) => {
     if (err) return callback(err)
-    if (destinationExists) return callback(null)
-    symlinkPaths(srcpath, dstpath, (err, relative) => {
+    srcpath = relative.toDst
+    symlinkType(relative.toCwd, type, (err, type) => {
       if (err) return callback(err)
-      srcpath = relative.toDst
-      symlinkType(relative.toCwd, type, (err, type) => {
+      const dir = path.dirname(dstpath)
+      pathExists(dir, (err, dirExists) => {
         if (err) return callback(err)
-        const dir = path.dirname(dstpath)
-        pathExists(dir, (err, dirExists) => {
+        if (dirExists) return fs.symlink(srcpath, dstpath, type, callback)
+        mkdirs(dir, err => {
           if (err) return callback(err)
-          if (dirExists) return fs.symlink(srcpath, dstpath, type, callback)
-          mkdirs(dir, err => {
-            if (err) return callback(err)
-            fs.symlink(srcpath, dstpath, type, callback)
-          })
+          fs.symlink(srcpath, dstpath, type, callback)
         })
       })
     })
@@ -44,8 +56,15 @@ function createSymlink (srcpath, dstpath, type, callback) {
 }
 
 function createSymlinkSync (srcpath, dstpath, type) {
-  const destinationExists = fs.existsSync(dstpath)
-  if (destinationExists) return undefined
+  let stats
+  try {
+    stats = fs.lstatSync(dstpath)
+  } catch {}
+  if (stats && stats.isSymbolicLink()) {
+    const srcStat = fs.statSync(srcpath)
+    const dstStat = fs.statSync(dstpath)
+    if (areIdentical(srcStat, dstStat)) return
+  }
 
   const relative = symlinkPathsSync(srcpath, dstpath)
   srcpath = relative.toDst
diff --git a/lib/move-sync/move-sync.js b/lib/move-sync/move-sync.js
index 20f910c..7e13587 100644
--- a/lib/move-sync/move-sync.js
+++ b/lib/move-sync/move-sync.js
@@ -11,13 +11,14 @@ function moveSync (src, dest, opts) {
   opts = opts || {}
   const overwrite = opts.overwrite || opts.clobber || false
 
-  const { srcStat } = stat.checkPathsSync(src, dest, 'move')
+  const { srcStat, isChangingCase = false } = stat.checkPathsSync(src, dest, 'move', opts)
   stat.checkParentPathsSync(src, srcStat, dest, 'move')
   mkdirpSync(path.dirname(dest))
-  return doRename(src, dest, overwrite)
+  return doRename(src, dest, overwrite, isChangingCase)
 }
 
-function doRename (src, dest, overwrite) {
+function doRename (src, dest, overwrite, isChangingCase) {
+  if (isChangingCase) return rename(src, dest, overwrite)
   if (overwrite) {
     removeSync(dest)
     return rename(src, dest, overwrite)
diff --git a/lib/move/move.js b/lib/move/move.js
index fa3ea61..23840e0 100644
--- a/lib/move/move.js
+++ b/lib/move/move.js
@@ -16,20 +16,21 @@ function move (src, dest, opts, cb) {
 
   const overwrite = opts.overwrite || opts.clobber || false
 
-  stat.checkPaths(src, dest, 'move', (err, stats) => {
+  stat.checkPaths(src, dest, 'move', opts, (err, stats) => {
     if (err) return cb(err)
-    const { srcStat } = stats
+    const { srcStat, isChangingCase = false } = stats
     stat.checkParentPaths(src, srcStat, dest, 'move', err => {
       if (err) return cb(err)
       mkdirp(path.dirname(dest), err => {
         if (err) return cb(err)
-        return doRename(src, dest, overwrite, cb)
+        return doRename(src, dest, overwrite, isChangingCase, cb)
       })
     })
   })
 }
 
-function doRename (src, dest, overwrite, cb) {
+function doRename (src, dest, overwrite, isChangingCase, cb) {
+  if (isChangingCase) return rename(src, dest, overwrite, cb)
   if (overwrite) {
     return remove(dest, err => {
       if (err) return cb(err)
diff --git a/lib/util/stat.js b/lib/util/stat.js
index 0b1c1b0..4f4ce98 100644
--- a/lib/util/stat.js
+++ b/lib/util/stat.js
@@ -7,23 +7,27 @@ const atLeastNode = require('at-least-node')
 
 const nodeSupportsBigInt = atLeastNode('10.5.0')
 const stat = (file) => nodeSupportsBigInt ? fs.stat(file, { bigint: true }) : fs.stat(file)
+const lstat = (file) => nodeSupportsBigInt ? fs.lstat(file, { bigint: true }) : fs.lstat(file)
 const statSync = (file) => nodeSupportsBigInt ? fs.statSync(file, { bigint: true }) : fs.statSync(file)
+const lstatSync = (file) => nodeSupportsBigInt ? fs.lstatSync(file, { bigint: true }) : fs.lstatSync(file)
 
-function getStats (src, dest) {
+function getStats (src, dest, opts) {
+  const statFunc = opts.dereference ? stat : lstat
   return Promise.all([
-    stat(src),
-    stat(dest).catch(err => {
+    statFunc(src),
+    statFunc(dest).catch(err => {
       if (err.code === 'ENOENT') return null
       throw err
     })
   ]).then(([srcStat, destStat]) => ({ srcStat, destStat }))
 }
 
-function getStatsSync (src, dest) {
+function getStatsSync (src, dest, opts) {
   let destStat
-  const srcStat = statSync(src)
+  const statFunc = opts.dereference ? statSync : lstatSync
+  const srcStat = statFunc(src)
   try {
-    destStat = statSync(dest)
+    destStat = statFunc(dest)
   } catch (err) {
     if (err.code === 'ENOENT') return { srcStat, destStat: null }
     throw err
@@ -31,13 +35,30 @@ function getStatsSync (src, dest) {
   return { srcStat, destStat }
 }
 
-function checkPaths (src, dest, funcName, cb) {
-  util.callbackify(getStats)(src, dest, (err, stats) => {
+function checkPaths (src, dest, funcName, opts, cb) {
+  util.callbackify(getStats)(src, dest, opts, (err, stats) => {
     if (err) return cb(err)
     const { srcStat, destStat } = stats
-    if (destStat && areIdentical(srcStat, destStat)) {
-      return cb(new Error('Source and destination must not be the same.'))
+
+    if (destStat) {
+      if (areIdentical(srcStat, destStat)) {
+        const srcBaseName = path.basename(src)
+        const destBaseName = path.basename(dest)
+        if (funcName === 'move' &&
+          srcBaseName !== destBaseName &&
+          srcBaseName.toLowerCase() === destBaseName.toLowerCase()) {
+          return cb(null, { srcStat, destStat, isChangingCase: true })
+        }
+        return cb(new Error('Source and destination must not be the same.'))
+      }
+      if (srcStat.isDirectory() && !destStat.isDirectory()) {
+        return cb(new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`))
+      }
+      if (!srcStat.isDirectory() && destStat.isDirectory()) {
+        return cb(new Error(`Cannot overwrite directory '${dest}' with non-directory '${src}'.`))
+      }
     }
+
     if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
       return cb(new Error(errMsg(src, dest, funcName)))
     }
@@ -45,11 +66,28 @@ function checkPaths (src, dest, funcName, cb) {
   })
 }
 
-function checkPathsSync (src, dest, funcName) {
-  const { srcStat, destStat } = getStatsSync(src, dest)
-  if (destStat && areIdentical(srcStat, destStat)) {
-    throw new Error('Source and destination must not be the same.')
+function checkPathsSync (src, dest, funcName, opts) {
+  const { srcStat, destStat } = getStatsSync(src, dest, opts)
+
+  if (destStat) {
+    if (areIdentical(srcStat, destStat)) {
+      const srcBaseName = path.basename(src)
+      const destBaseName = path.basename(dest)
+      if (funcName === 'move' &&
+        srcBaseName !== destBaseName &&
+        srcBaseName.toLowerCase() === destBaseName.toLowerCase()) {
+        return { srcStat, destStat, isChangingCase: true }
+      }
+      throw new Error('Source and destination must not be the same.')
+    }
+    if (srcStat.isDirectory() && !destStat.isDirectory()) {
+      throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)
+    }
+    if (!srcStat.isDirectory() && destStat.isDirectory()) {
+      throw new Error(`Cannot overwrite directory '${dest}' with non-directory '${src}'.`)
+    }
   }
+
   if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
     throw new Error(errMsg(src, dest, funcName))
   }
@@ -135,5 +173,6 @@ module.exports = {
   checkPathsSync,
   checkParentPaths,
   checkParentPathsSync,
-  isSrcSubdir
+  isSrcSubdir,
+  areIdentical
 }


Test patch:
diff --git a/lib/copy-sync/__tests__/broken-symlink.test.js b/lib/copy-sync/__tests__/copy-sync-broken-symlink.test.js
similarity index 67%
rename from lib/copy-sync/__tests__/broken-symlink.test.js
rename to lib/copy-sync/__tests__/copy-sync-broken-symlink.test.js
index d6d5b57..33ba910 100644
--- a/lib/copy-sync/__tests__/broken-symlink.test.js
+++ b/lib/copy-sync/__tests__/copy-sync-broken-symlink.test.js
@@ -2,7 +2,7 @@
 
 const fs = require('fs')
 const os = require('os')
-const fse = require('../../')
+const fse = require('../..')
 const path = require('path')
 const assert = require('assert')
 const copySync = require('../copy-sync')
@@ -10,9 +10,9 @@ const copySync = require('../copy-sync')
 /* global afterEach, beforeEach, describe, it */
 
 describe('copy-sync / broken symlink', () => {
-  const TEST_DIR = path.join(os.tmpdir(), 'fs-extra', 'copy-sync-broken-symlinks')
+  const TEST_DIR = path.join(os.tmpdir(), 'fs-extra', 'copy-sync-broken-symlink')
   const src = path.join(TEST_DIR, 'src')
-  const out = path.join(TEST_DIR, 'out')
+  const dest = path.join(TEST_DIR, 'dest')
 
   beforeEach(done => {
     fse.emptyDir(TEST_DIR, err => {
@@ -23,12 +23,20 @@ describe('copy-sync / broken symlink', () => {
 
   afterEach(done => fse.remove(TEST_DIR, done))
 
-  it('should error if symlink is broken', () => {
-    assert.throws(() => copySync(src, out))
-  })
+  describe('when symlink is broken', () => {
+    it('should not throw error if dereference is false', () => {
+      let err = null
+      try {
+        copySync(src, dest)
+      } catch (e) {
+        err = e
+      }
+      assert.strictEqual(err, null)
+    })
 
-  it('should throw an error when dereference=true', () => {
-    assert.throws(() => copySync(src, out, { dereference: true }), err => err.code === 'ENOENT')
+    it('should throw error if dereference is true', () => {
+      assert.throws(() => copySync(src, dest, { dereference: true }), err => err.code === 'ENOENT')
+    })
   })
 })
 
diff --git a/lib/copy-sync/__tests__/copy-sync-file.test.js b/lib/copy-sync/__tests__/copy-sync-file.test.js
index 1218fce..6ffff60 100644
--- a/lib/copy-sync/__tests__/copy-sync-file.test.js
+++ b/lib/copy-sync/__tests__/copy-sync-file.test.js
@@ -21,6 +21,21 @@ describe('+ copySync() / file', () => {
   afterEach(done => fs.remove(TEST_DIR, done))
 
   describe('> when src is a file', () => {
+    describe('> when dest exists and is a directory', () => {
+      it('should throw error', () => {
+        const src = path.join(TEST_DIR, 'file.txt')
+        const dest = path.join(TEST_DIR, 'dir')
+        fs.ensureFileSync(src)
+        fs.ensureDirSync(dest)
+
+        try {
+          fs.copySync(src, dest)
+        } catch (err) {
+          assert.strictEqual(err.message, `Cannot overwrite directory '${dest}' with non-directory '${src}'.`)
+        }
+      })
+    })
+
     it('should copy the file synchronously', () => {
       const fileSrc = path.join(TEST_DIR, 'TEST_fs-extra_src')
       const fileDest = path.join(TEST_DIR, 'TEST_fs-extra_copy')
diff --git a/lib/copy-sync/__tests__/copy-sync-prevent-copying-identical.test.js b/lib/copy-sync/__tests__/copy-sync-prevent-copying-identical.test.js
index 87135a9..c345909 100644
--- a/lib/copy-sync/__tests__/copy-sync-prevent-copying-identical.test.js
+++ b/lib/copy-sync/__tests__/copy-sync-prevent-copying-identical.test.js
@@ -113,7 +113,7 @@ describe('+ copySync() - prevent copying identical files and dirs', () => {
 
   describe('> when src is a directory', () => {
     describe('>> when src is regular and dest is a symlink that points to src', () => {
-      it('should error', () => {
+      it('should error if dereference is true', () => {
         src = path.join(TEST_DIR, 'src')
         fs.mkdirsSync(src)
         const subdir = path.join(TEST_DIR, 'src', 'subdir')
@@ -126,7 +126,7 @@ describe('+ copySync() - prevent copying identical files and dirs', () => {
         const oldlen = klawSync(src).length
 
         try {
-          fs.copySync(src, destLink)
+          fs.copySync(src, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
         }
@@ -166,7 +166,7 @@ describe('+ copySync() - prevent copying identical files and dirs', () => {
     })
 
     describe('>> when src and dest are symlinks that point to the exact same path', () => {
-      it('should error src and dest are the same', () => {
+      it('should error if src and dest are the same and dereferene is true', () => {
         src = path.join(TEST_DIR, 'src')
         fs.mkdirsSync(src)
         const srcLink = path.join(TEST_DIR, 'src_symlink')
@@ -178,7 +178,7 @@ describe('+ copySync() - prevent copying identical files and dirs', () => {
         const destlenBefore = klawSync(destLink).length
 
         try {
-          fs.copySync(srcLink, destLink)
+          fs.copySync(srcLink, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
         }
@@ -203,7 +203,7 @@ describe('+ copySync() - prevent copying identical files and dirs', () => {
 
   describe('> when src is a file', () => {
     describe('>> when src is regular and dest is a symlink that points to src', () => {
-      it('should error', () => {
+      it('should error if dereference is true', () => {
         src = path.join(TEST_DIR, 'src', 'somefile.txt')
         fs.ensureFileSync(src)
         fs.writeFileSync(src, 'some data')
@@ -212,7 +212,7 @@ describe('+ copySync() - prevent copying identical files and dirs', () => {
         fs.symlinkSync(src, destLink, 'file')
 
         try {
-          fs.copySync(src, destLink)
+          fs.copySync(src, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
         }
@@ -243,7 +243,7 @@ describe('+ copySync() - prevent copying identical files and dirs', () => {
     })
 
     describe('>> when src and dest are symlinks that point to the exact same path', () => {
-      it('should error src and dest are the same', () => {
+      it('should error if src and dest are the same and dereference is true', () => {
         src = path.join(TEST_DIR, 'src', 'srcfile.txt')
         fs.outputFileSync(src, 'src data')
 
@@ -254,7 +254,7 @@ describe('+ copySync() - prevent copying identical files and dirs', () => {
         fs.symlinkSync(src, destLink, 'file')
 
         try {
-          fs.copySync(srcLink, destLink)
+          fs.copySync(srcLink, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
         }
diff --git a/lib/copy-sync/__tests__/copy-sync-prevent-copying-into-itself.test.js b/lib/copy-sync/__tests__/copy-sync-prevent-copying-into-itself.test.js
index f9418cb..24bdd06 100644
--- a/lib/copy-sync/__tests__/copy-sync-prevent-copying-into-itself.test.js
+++ b/lib/copy-sync/__tests__/copy-sync-prevent-copying-into-itself.test.js
@@ -146,7 +146,7 @@ describe('+ copySync() - prevent copying into itself', () => {
     })
 
     describe('>> when dest is a symlink', () => {
-      it('should error when dest points exactly to src', () => {
+      it('should error when dest points exactly to src and dereference is true', () => {
         const destLink = path.join(TEST_DIR, 'dest-symlink')
         fs.symlinkSync(src, destLink, 'dir')
 
@@ -154,7 +154,7 @@ describe('+ copySync() - prevent copying into itself', () => {
         assert(srclenBefore > 2)
 
         try {
-          fs.copySync(src, destLink)
+          fs.copySync(src, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
         }
@@ -216,7 +216,7 @@ describe('+ copySync() - prevent copying into itself', () => {
         }
       })
 
-      it('should copy the directory successfully when src is a subdir of resolved dest path', () => {
+      it('should copy the directory successfully when src is a subdir of resolved dest path and dereferene is true', () => {
         const srcInDest = path.join(TEST_DIR, 'dest', 'some', 'nested', 'src')
         const destLink = path.join(TEST_DIR, 'dest-symlink')
         fs.copySync(src, srcInDest) // put some stuff in srcInDest
@@ -226,9 +226,9 @@ describe('+ copySync() - prevent copying into itself', () => {
 
         const srclen = klawSync(srcInDest).length
         const destlenBefore = klawSync(dest).length
-
         assert(srclen > 2)
-        fs.copySync(srcInDest, destLink)
+
+        fs.copySync(srcInDest, destLink, { dereference: true })
 
         const destlenAfter = klawSync(dest).length
 
@@ -323,7 +323,7 @@ describe('+ copySync() - prevent copying into itself', () => {
     })
 
     describe('>> when dest is a symlink', () => {
-      it('should error when resolved dest path is exactly the same as resolved src path', () => {
+      it('should error when resolved dest path is exactly the same as resolved src path and dereference is true', () => {
         const srcLink = path.join(TEST_DIR, 'src-symlink')
         fs.symlinkSync(src, srcLink, 'dir')
         const destLink = path.join(TEST_DIR, 'dest-symlink')
@@ -335,7 +335,7 @@ describe('+ copySync() - prevent copying into itself', () => {
         assert(destlenBefore > 2)
 
         try {
-          fs.copySync(srcLink, destLink)
+          fs.copySync(srcLink, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
         } finally {
diff --git a/lib/copy-sync/__tests__/symlink.test.js b/lib/copy-sync/__tests__/copy-sync-symlink.test.js
similarity index 98%
rename from lib/copy-sync/__tests__/symlink.test.js
rename to lib/copy-sync/__tests__/copy-sync-symlink.test.js
index c6e5508..3f7cfe1 100644
--- a/lib/copy-sync/__tests__/symlink.test.js
+++ b/lib/copy-sync/__tests__/copy-sync-symlink.test.js
@@ -1,7 +1,7 @@
 'use strict'
 
 const os = require('os')
-const fs = require('../../')
+const fs = require('../..')
 const path = require('path')
 const assert = require('assert')
 const copySync = require('../copy-sync')
diff --git a/lib/copy/__tests__/copy-broken-symlink.test.js b/lib/copy/__tests__/copy-broken-symlink.test.js
new file mode 100644
index 0000000..81e46de
--- /dev/null
+++ b/lib/copy/__tests__/copy-broken-symlink.test.js
@@ -0,0 +1,62 @@
+'use strict'
+
+const fs = require('fs')
+const os = require('os')
+const fse = require('../..')
+const path = require('path')
+const assert = require('assert')
+const copy = require('../copy')
+
+/* global afterEach, beforeEach, describe, it */
+
+describe('copy / broken symlink', () => {
+  const TEST_DIR = path.join(os.tmpdir(), 'fs-extra', 'copy-broken-symlink')
+  const src = path.join(TEST_DIR, 'src')
+  const dest = path.join(TEST_DIR, 'dest')
+
+  beforeEach(done => {
+    fse.emptyDir(TEST_DIR, err => {
+      assert.ifError(err)
+      createFixtures(src, done)
+    })
+  })
+
+  afterEach(done => fse.remove(TEST_DIR, done))
+
+  describe('when symlink is broken', () => {
+    it('should not throw error if dereference is false', done => {
+      copy(src, dest, err => {
+        assert.strictEqual(err, null)
+        done()
+      })
+    })
+
+    it('should throw error if dereference is true', done => {
+      copy(src, dest, { dereference: true }, err => {
+        assert.strictEqual(err.code, 'ENOENT')
+        done()
+      })
+    })
+  })
+})
+
+function createFixtures (srcDir, callback) {
+  fs.mkdir(srcDir, err => {
+    let brokenFile
+    let brokenFileLink
+
+    if (err) return callback(err)
+
+    try {
+      brokenFile = path.join(srcDir, 'does-not-exist')
+      brokenFileLink = path.join(srcDir, 'broken-symlink')
+      fs.writeFileSync(brokenFile, 'does not matter')
+      fs.symlinkSync(brokenFile, brokenFileLink, 'file')
+    } catch (err) {
+      callback(err)
+    }
+
+    // break the symlink now
+    fse.remove(brokenFile, callback)
+  })
+}
diff --git a/lib/copy/__tests__/copy-prevent-copying-identical.test.js b/lib/copy/__tests__/copy-prevent-copying-identical.test.js
index b79674a..4c6ebe9 100644
--- a/lib/copy/__tests__/copy-prevent-copying-identical.test.js
+++ b/lib/copy/__tests__/copy-prevent-copying-identical.test.js
@@ -104,7 +104,7 @@ describe('+ copy() - prevent copying identical files and dirs', () => {
 
   describe('> when src is a directory', () => {
     describe('>> when src is regular and dest is a symlink that points to src', () => {
-      it('should error', done => {
+      it('should error if dereference is true', done => {
         src = path.join(TEST_DIR, 'src')
         fs.mkdirsSync(src)
         const subdir = path.join(TEST_DIR, 'src', 'subdir')
@@ -116,7 +116,7 @@ describe('+ copy() - prevent copying identical files and dirs', () => {
 
         const oldlen = klawSync(src).length
 
-        fs.copy(src, destLink, err => {
+        fs.copy(src, destLink, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
 
           const newlen = klawSync(src).length
@@ -155,7 +155,7 @@ describe('+ copy() - prevent copying identical files and dirs', () => {
     })
 
     describe('>> when src and dest are symlinks that point to the exact same path', () => {
-      it('should error src and dest are the same', done => {
+      it('should error src and dest are the same and dereference is true', done => {
         src = path.join(TEST_DIR, 'src')
         fs.mkdirsSync(src)
         const srcLink = path.join(TEST_DIR, 'src_symlink')
@@ -166,7 +166,7 @@ describe('+ copy() - prevent copying identical files and dirs', () => {
         const srclenBefore = klawSync(srcLink).length
         const destlenBefore = klawSync(destLink).length
 
-        fs.copy(srcLink, destLink, err => {
+        fs.copy(srcLink, destLink, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
 
           const srclenAfter = klawSync(srcLink).length
@@ -198,7 +198,7 @@ describe('+ copy() - prevent copying identical files and dirs', () => {
         const destLink = path.join(TEST_DIR, 'dest-symlink')
         fs.symlinkSync(src, destLink, 'file')
 
-        fs.copy(src, destLink, err => {
+        fs.copy(src, destLink, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
           done()
         })
@@ -206,14 +206,14 @@ describe('+ copy() - prevent copying identical files and dirs', () => {
     })
 
     describe('>> when src is a symlink that points to a regular dest', () => {
-      it('should throw error', done => {
+      it('should throw error if dereference is true', done => {
         dest = path.join(TEST_DIR, 'dest', 'somefile.txt')
         fs.outputFileSync(dest, 'some data')
 
         const srcLink = path.join(TEST_DIR, 'src-symlink')
         fs.symlinkSync(dest, srcLink, 'file')
 
-        fs.copy(srcLink, dest, err => {
+        fs.copy(srcLink, dest, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
 
           const link = fs.readlinkSync(srcLink)
@@ -225,7 +225,7 @@ describe('+ copy() - prevent copying identical files and dirs', () => {
     })
 
     describe('>> when src and dest are symlinks that point to the exact same path', () => {
-      it('should error src and dest are the same', done => {
+      it('should error src and dest are the same and dereferene is true', done => {
         src = path.join(TEST_DIR, 'src', 'srcfile.txt')
         fs.outputFileSync(src, 'src data')
 
@@ -235,7 +235,7 @@ describe('+ copy() - prevent copying identical files and dirs', () => {
         const destLink = path.join(TEST_DIR, 'dest_symlink')
         fs.symlinkSync(src, destLink, 'file')
 
-        fs.copy(srcLink, destLink, err => {
+        fs.copy(srcLink, destLink, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
 
           const srcln = fs.readlinkSync(srcLink)
diff --git a/lib/copy/__tests__/copy-prevent-copying-into-itself.test.js b/lib/copy/__tests__/copy-prevent-copying-into-itself.test.js
index 7c62923..4e0fd4a 100644
--- a/lib/copy/__tests__/copy-prevent-copying-into-itself.test.js
+++ b/lib/copy/__tests__/copy-prevent-copying-into-itself.test.js
@@ -149,14 +149,14 @@ describe('+ copy() - prevent copying into itself', () => {
     })
 
     describe('>> when dest is a symlink', () => {
-      it('should error when dest points exactly to src', done => {
+      it('should error when dest points exactly to src and dereference is true', done => {
         const destLink = path.join(TEST_DIR, 'dest-symlink')
         fs.symlinkSync(src, destLink, 'dir')
 
         const srclenBefore = klawSync(src).length
         assert(srclenBefore > 2)
 
-        fs.copy(src, destLink, err => {
+        fs.copy(src, destLink, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
 
           const srclenAfter = klawSync(src).length
@@ -210,7 +210,7 @@ describe('+ copy() - prevent copying into itself', () => {
         })
       })
 
-      it('should copy the directory successfully when src is a subdir of resolved dest path', done => {
+      it('should copy the directory successfully when src is a subdir of resolved dest path and dereference is true', done => {
         const srcInDest = path.join(TEST_DIR, 'dest', 'some', 'nested', 'src')
         const destLink = path.join(TEST_DIR, 'dest-symlink')
         fs.copySync(src, srcInDest) // put some stuff in srcInDest
@@ -222,7 +222,7 @@ describe('+ copy() - prevent copying into itself', () => {
         const destlenBefore = klawSync(dest).length
 
         assert(srclen > 2)
-        fs.copy(srcInDest, destLink, err => {
+        fs.copy(srcInDest, destLink, { dereference: true }, err => {
           assert.ifError(err)
 
           const destlenAfter = klawSync(dest).length
@@ -321,7 +321,7 @@ describe('+ copy() - prevent copying into itself', () => {
     })
 
     describe('>> when dest is a symlink', () => {
-      it('should error when resolved dest path is exactly the same as resolved src path', done => {
+      it('should error when resolved dest path is exactly the same as resolved src path and dereference is true', done => {
         const srcLink = path.join(TEST_DIR, 'src-symlink')
         fs.symlinkSync(src, srcLink, 'dir')
         const destLink = path.join(TEST_DIR, 'dest-symlink')
@@ -332,7 +332,7 @@ describe('+ copy() - prevent copying into itself', () => {
         assert(srclenBefore > 2)
         assert(destlenBefore > 2)
 
-        fs.copy(srcLink, destLink, err => {
+        fs.copy(srcLink, destLink, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
 
           const srclenAfter = klawSync(srcLink).length
@@ -364,24 +364,6 @@ describe('+ copy() - prevent copying into itself', () => {
           done()
         })
       })
-
-      it('should error when resolved src path is a subdir of resolved dest path', done => {
-        const srcInDest = path.join(TEST_DIR, 'dest', 'some', 'nested', 'src')
-        const srcLink = path.join(TEST_DIR, 'src-symlink')
-        const destLink = path.join(TEST_DIR, 'dest-symlink')
-        const dest = path.join(TEST_DIR, 'dest')
-
-        fs.ensureDirSync(srcInDest)
-        fs.ensureSymlinkSync(srcInDest, srcLink, 'dir')
-        fs.ensureSymlinkSync(dest, destLink, 'dir')
-
-        fs.copy(srcLink, destLink, err => {
-          assert.strictEqual(err.message, `Cannot overwrite '${dest}' with '${srcInDest}'.`)
-          const destln = fs.readlinkSync(destLink)
-          assert.strictEqual(destln, dest)
-          done()
-        })
-      })
     })
   })
 })
diff --git a/lib/copy/__tests__/copy.test.js b/lib/copy/__tests__/copy.test.js
index 5cc07e3..e7eed97 100644
--- a/lib/copy/__tests__/copy.test.js
+++ b/lib/copy/__tests__/copy.test.js
@@ -123,6 +123,20 @@ describe('fs-extra', () => {
           })
         })
       })
+
+      describe('> when dest exists and is a directory', () => {
+        it('should return an error', done => {
+          const src = path.join(TEST_DIR, 'file.txt')
+          const dest = path.join(TEST_DIR, 'dir')
+          fse.ensureFileSync(src)
+          fse.ensureDirSync(dest)
+
+          fse.copy(src, dest, err => {
+            assert.strictEqual(err.message, `Cannot overwrite directory '${dest}' with non-directory '${src}'.`)
+            done()
+          })
+        })
+      })
     })
 
     describe('> when src is a directory', () => {
diff --git a/lib/copy/__tests__/ncp/broken-symlink.test.js b/lib/copy/__tests__/ncp/broken-symlink.test.js
index 572e821..ba39808 100644
--- a/lib/copy/__tests__/ncp/broken-symlink.test.js
+++ b/lib/copy/__tests__/ncp/broken-symlink.test.js
@@ -23,14 +23,14 @@ describe('ncp broken symlink', () => {
 
   afterEach(done => fse.remove(TEST_DIR, done))
 
-  it('should error if symlink is broken', done => {
+  it('should not error if symlink is broken', done => {
     ncp(src, out, err => {
-      assert(err)
+      assert.strictEqual(err, null)
       done()
     })
   })
 
-  it('should return an error when dereference=true', done => {
+  it('should return an error if symlink is broken and dereference=true', done => {
     ncp(src, out, { dereference: true }, err => {
       assert.strictEqual(err.code, 'ENOENT')
       done()
diff --git a/lib/ensure/__tests__/link.test.js b/lib/ensure/__tests__/link.test.js
index b78313e..83dc869 100644
--- a/lib/ensure/__tests__/link.test.js
+++ b/lib/ensure/__tests__/link.test.js
@@ -26,6 +26,8 @@ describe('fse-ensure-link', () => {
     [['./foo.txt', './alpha/link.txt'], 'file-error', 'file-success'],
     [['./foo.txt', './alpha/beta/link.txt'], 'file-error', 'file-success'],
     [['./foo.txt', './alpha/beta/gamma/link.txt'], 'file-error', 'file-success'],
+    [['./foo.txt', './link-foo.txt'], 'file-error', 'file-success'],
+    [['./dir-foo/foo.txt', './link-foo.txt'], 'file-error', 'file-error'],
     [['./missing.txt', './link.txt'], 'file-error', 'file-error'],
     [['./missing.txt', './missing-dir/link.txt'], 'file-error', 'file-error'],
     [['./foo.txt', './link.txt'], 'file-success', 'file-success'],
@@ -34,7 +36,7 @@ describe('fse-ensure-link', () => {
     [['../foo.txt', './link.txt'], 'file-error', 'file-error'],
     [['../dir-foo/foo.txt', './link.txt'], 'file-error', 'file-error'],
     // error is thrown if destination path exists
-    [['./foo.txt', './dir-foo/foo.txt'], 'file-error', 'file-dest-exists'],
+    [['./foo.txt', './dir-foo/foo.txt'], 'file-error', 'file-error'],
     [[path.resolve(path.join(TEST_DIR, './foo.txt')), './link.txt'], 'file-success', 'file-success'],
     [[path.resolve(path.join(TEST_DIR, './dir-foo/foo.txt')), './link.txt'], 'file-success', 'file-success'],
     [[path.resolve(path.join(TEST_DIR, './missing.txt')), './link.txt'], 'file-error', 'file-error'],
@@ -55,6 +57,7 @@ describe('fse-ensure-link', () => {
     fse.mkdirsSync('dir-bar')
     fs.writeFileSync('dir-bar/bar.txt', 'dir-bar\n')
     fse.mkdirsSync('real-alpha/real-beta/real-gamma')
+    fs.linkSync('foo.txt', 'link-foo.txt')
   })
 
   afterEach(done => fse.emptyDir(TEST_DIR, done))
@@ -107,23 +110,6 @@ describe('fse-ensure-link', () => {
     })
   }
 
-  function fileDestExists (args, fn) {
-    const srcpath = args[0]
-    const dstpath = args[1]
-
-    it(`should do nothing using src ${srcpath} and dst ${dstpath}`, done => {
-      const destinationContentBefore = fs.readFileSync(dstpath, 'utf8')
-      const callback = err => {
-        if (err) return done(err)
-        const destinationContentAfter = fs.readFileSync(dstpath, 'utf8')
-        assert.strictEqual(destinationContentBefore, destinationContentAfter)
-        return done()
-      }
-      args.push(callback)
-      return fn(...args)
-    })
-  }
-
   function fileSuccessSync (args, fn) {
     const srcpath = args[0]
     const dstpath = args[1]
@@ -161,18 +147,6 @@ describe('fse-ensure-link', () => {
     })
   }
 
-  function fileDestExistsSync (args, fn) {
-    const srcpath = args[0]
-    const dstpath = args[1]
-
-    it(`should do nothing using src ${srcpath} and dst ${dstpath}`, () => {
-      const destinationContentBefore = fs.readFileSync(dstpath, 'utf8')
-      fn(...args)
-      const destinationContentAfter = fs.readFileSync(dstpath, 'utf8')
-      assert.strictEqual(destinationContentBefore, destinationContentAfter)
-    })
-  }
-
   describe('fs.link()', () => {
     const fn = fs.link
     tests.forEach(test => {
@@ -181,7 +155,6 @@ describe('fse-ensure-link', () => {
       // const newBehavior = test[2]
       if (nativeBehavior === 'file-success') fileSuccess(args, fn)
       if (nativeBehavior === 'file-error') fileError(args, fn)
-      if (nativeBehavior === 'file-dest-exists') fileDestExists(args, fn)
     })
   })
 
@@ -193,7 +166,6 @@ describe('fse-ensure-link', () => {
       const newBehavior = test[2]
       if (newBehavior === 'file-success') fileSuccess(args, fn)
       if (newBehavior === 'file-error') fileError(args, fn)
-      if (newBehavior === 'file-dest-exists') fileDestExists(args, fn)
     })
   })
 
@@ -229,7 +201,6 @@ describe('fse-ensure-link', () => {
       // const newBehavior = test[2]
       if (nativeBehavior === 'file-success') fileSuccessSync(args, fn)
       if (nativeBehavior === 'file-error') fileErrorSync(args, fn)
-      if (nativeBehavior === 'file-dest-exists') fileDestExists(args, fn)
     })
   })
 
@@ -241,7 +212,6 @@ describe('fse-ensure-link', () => {
       const newBehavior = test[2]
       if (newBehavior === 'file-success') fileSuccessSync(args, fn)
       if (newBehavior === 'file-error') fileErrorSync(args, fn)
-      if (newBehavior === 'file-dest-exists') fileDestExistsSync(args, fn)
     })
   })
 })
diff --git a/lib/ensure/__tests__/symlink.test.js b/lib/ensure/__tests__/symlink.test.js
index 22a0043..0c951ef 100644
--- a/lib/ensure/__tests__/symlink.test.js
+++ b/lib/ensure/__tests__/symlink.test.js
@@ -32,10 +32,12 @@ describe('fse-ensure-symlink', () => {
     [['./foo.txt', './alpha/symlink.txt'], 'file-error', 'file-success'],
     [['./foo.txt', './alpha/beta/symlink.txt'], 'file-error', 'file-success'],
     [['./foo.txt', './alpha/beta/gamma/symlink.txt'], 'file-error', 'file-success'],
+    [['./foo.txt', './real-symlink.txt'], 'file-error', 'file-success'],
+    [['./dir-foo/foo.txt', './real-symlink.txt'], 'file-error', 'file-error'],
     [['./missing.txt', './symlink.txt'], 'file-broken', 'file-error'],
     [['./missing.txt', './missing-dir/symlink.txt'], 'file-error', 'file-error'],
     // error is thrown if destination path exists
-    [['./foo.txt', './dir-foo/foo.txt'], 'file-error', 'file-dest-exists'],
+    [['./foo.txt', './dir-foo/foo.txt'], 'file-error', 'file-error'],
     [['./dir-foo', './symlink-dir-foo'], 'dir-success', 'dir-success'],
     [['../dir-bar', './dir-foo/symlink-dir-bar'], 'dir-success', 'dir-success'],
     [['./dir-bar', './dir-foo/symlink-dir-bar'], 'dir-broken', 'dir-success'],
@@ -46,9 +48,11 @@ describe('fse-ensure-symlink', () => {
     [['./dir-foo', './alpha/dir-foo'], 'dir-error', 'dir-success'],
     [['./dir-foo', './alpha/beta/dir-foo'], 'dir-error', 'dir-success'],
     [['./dir-foo', './alpha/beta/gamma/dir-foo'], 'dir-error', 'dir-success'],
+    [['./dir-foo', './real-symlink-dir-foo'], 'dir-error', 'dir-success'],
+    [['./dir-bar', './real-symlink-dir-foo'], 'dir-error', 'dir-error'],
     [['./missing', './dir-foo/symlink-dir-missing'], 'dir-broken', 'dir-error'],
     // error is thrown if destination path exists
-    [['./dir-foo', './real-alpha/real-beta'], 'dir-error', 'dir-dest-exists'],
+    [['./dir-foo', './real-alpha/real-beta'], 'dir-error', 'dir-error'],
     [[path.resolve(path.join(TEST_DIR, './foo.txt')), './symlink.txt'], 'file-success', 'file-success'],
     [[path.resolve(path.join(TEST_DIR, './dir-foo/foo.txt')), './symlink.txt'], 'file-success', 'file-success'],
     [[path.resolve(path.join(TEST_DIR, './missing.txt')), './symlink.txt'], 'file-broken', 'file-error'],
@@ -69,6 +73,8 @@ describe('fse-ensure-symlink', () => {
     fse.mkdirsSync('dir-bar')
     fs.writeFileSync('dir-bar/bar.txt', 'dir-bar\n')
     fse.mkdirsSync('real-alpha/real-beta/real-gamma')
+    fs.symlinkSync('foo.txt', 'real-symlink.txt')
+    fs.symlinkSync('dir-foo', 'real-symlink-dir-foo')
   })
 
   afterEach(done => fse.emptyDir(TEST_DIR, done))
@@ -138,22 +144,6 @@ describe('fse-ensure-symlink', () => {
     })
   }
 
-  function fileDestExists (args, fn) {
-    const srcpath = args[0]
-    const dstpath = args[1]
-    it(`should do nothing using src ${srcpath} and dst ${dstpath}`, done => {
-      const destinationContentBefore = fs.readFileSync(dstpath, 'utf8')
-      const callback = err => {
-        if (err) return done(err)
-        const destinationContentAfter = fs.readFileSync(dstpath, 'utf8')
-        assert.strictEqual(destinationContentBefore, destinationContentAfter)
-        return done()
-      }
-      args.push(callback)
-      return fn(...args)
-    })
-  }
-
   function dirSuccess (args, fn) {
     const srcpath = args[0]
     const dstpath = args[1]
@@ -214,22 +204,6 @@ describe('fse-ensure-symlink', () => {
     })
   }
 
-  function dirDestExists (args, fn) {
-    const srcpath = args[0]
-    const dstpath = args[1]
-    it(`should do nothing using src ${srcpath} and dst ${dstpath}`, done => {
-      const destinationContentBefore = fs.readdirSync(dstpath)
-      const callback = err => {
-        if (err) return done(err)
-        const destinationContentAfter = fs.readdirSync(dstpath)
-        assert.deepStrictEqual(destinationContentBefore, destinationContentAfter)
-        return done()
-      }
-      args.push(callback)
-      return fn(...args)
-    })
-  }
-
   function fileSuccessSync (args, fn) {
     const srcpath = args[0]
     const dstpath = args[1]
@@ -280,17 +254,6 @@ describe('fse-ensure-symlink', () => {
     })
   }
 
-  function fileDestExistsSync (args, fn) {
-    const srcpath = args[0]
-    const dstpath = args[1]
-    it(`should do nothing using src ${srcpath} and dst ${dstpath}`, () => {
-      const destinationContentBefore = fs.readFileSync(dstpath, 'utf8')
-      fn(...args)
-      const destinationContentAfter = fs.readFileSync(dstpath, 'utf8')
-      assert.strictEqual(destinationContentBefore, destinationContentAfter)
-    })
-  }
-
   function dirSuccessSync (args, fn) {
     const srcpath = args[0]
     const dstpath = args[1]
@@ -341,17 +304,6 @@ describe('fse-ensure-symlink', () => {
     })
   }
 
-  function dirDestExistsSync (args, fn) {
-    const srcpath = args[0]
-    const dstpath = args[1]
-    it(`should do nothing using src ${srcpath} and dst ${dstpath}`, () => {
-      const destinationContentBefore = fs.readdirSync(dstpath)
-      fn(...args)
-      const destinationContentAfter = fs.readdirSync(dstpath)
-      assert.deepStrictEqual(destinationContentBefore, destinationContentAfter)
-    })
-  }
-
   describe('fs.symlink()', () => {
     const fn = fs.symlink
     tests.forEach(test => {
@@ -361,12 +313,10 @@ describe('fse-ensure-symlink', () => {
       if (nativeBehavior === 'file-success') fileSuccess(args, fn)
       if (nativeBehavior === 'file-broken') fileBroken(args, fn)
       if (nativeBehavior === 'file-error') fileError(args, fn)
-      if (nativeBehavior === 'file-dest-exists') fileDestExists(args, fn)
       args.push('dir')
       if (nativeBehavior === 'dir-success') dirSuccess(args, fn)
       if (nativeBehavior === 'dir-broken') dirBroken(args, fn)
       if (nativeBehavior === 'dir-error') dirError(args, fn)
-      if (nativeBehavior === 'dir-dest-exists') dirDestExists(args, fn)
     })
   })
 
@@ -379,11 +329,9 @@ describe('fse-ensure-symlink', () => {
       if (newBehavior === 'file-success') fileSuccess(args, fn)
       if (newBehavior === 'file-broken') fileBroken(args, fn)
       if (newBehavior === 'file-error') fileError(args, fn)
-      if (newBehavior === 'file-dest-exists') fileDestExists(args, fn)
       if (newBehavior === 'dir-success') dirSuccess(args, fn)
       if (newBehavior === 'dir-broken') dirBroken(args, fn)
       if (newBehavior === 'dir-error') dirError(args, fn)
-      if (newBehavior === 'dir-dest-exists') dirDestExists(args, fn)
     })
   })
 
@@ -419,12 +367,10 @@ describe('fse-ensure-symlink', () => {
       if (nativeBehavior === 'file-success') fileSuccessSync(args, fn)
       if (nativeBehavior === 'file-broken') fileBrokenSync(args, fn)
       if (nativeBehavior === 'file-error') fileErrorSync(args, fn)
-      if (nativeBehavior === 'file-dest-exists') fileDestExistsSync(args, fn)
       args.push('dir')
       if (nativeBehavior === 'dir-success') dirSuccessSync(args, fn)
       if (nativeBehavior === 'dir-broken') dirBrokenSync(args, fn)
       if (nativeBehavior === 'dir-error') dirErrorSync(args, fn)
-      if (nativeBehavior === 'dir-dest-exists') dirDestExistsSync(args, fn)
     })
   })
 
@@ -437,11 +383,9 @@ describe('fse-ensure-symlink', () => {
       if (newBehavior === 'file-success') fileSuccessSync(args, fn)
       if (newBehavior === 'file-broken') fileBrokenSync(args, fn)
       if (newBehavior === 'file-error') fileErrorSync(args, fn)
-      if (newBehavior === 'file-dest-exists') fileDestExistsSync(args, fn)
       if (newBehavior === 'dir-success') dirSuccessSync(args, fn)
       if (newBehavior === 'dir-broken') dirBrokenSync(args, fn)
       if (newBehavior === 'dir-error') dirErrorSync(args, fn)
-      if (newBehavior === 'dir-dest-exists') dirDestExistsSync(args, fn)
     })
   })
 })
diff --git a/lib/move-sync/__tests__/move-sync-case-insensitive-paths.test.js b/lib/move-sync/__tests__/move-sync-case-insensitive-paths.test.js
index 32600b8..4cf29e1 100644
--- a/lib/move-sync/__tests__/move-sync-case-insensitive-paths.test.js
+++ b/lib/move-sync/__tests__/move-sync-case-insensitive-paths.test.js
@@ -4,7 +4,6 @@ const assert = require('assert')
 const os = require('os')
 const path = require('path')
 const fs = require('../../')
-const platform = os.platform()
 
 /* global beforeEach, afterEach, describe, it */
 
@@ -21,104 +20,56 @@ describe('+ moveSync() - case insensitive paths', () => {
   afterEach(() => fs.removeSync(TEST_DIR))
 
   describe('> when src is a directory', () => {
-    it('should behave correctly based on the OS', () => {
+    it('should move successfully', () => {
       src = path.join(TEST_DIR, 'srcdir')
       fs.outputFileSync(path.join(src, 'subdir', 'file.txt'), 'some data')
       dest = path.join(TEST_DIR, 'srcDir')
-      let errThrown = false
 
-      try {
-        fs.moveSync(src, dest)
-      } catch (err) {
-        if (platform === 'darwin' || platform === 'win32') {
-          assert.strictEqual(err.message, 'Source and destination must not be the same.')
-          errThrown = true
-        }
-      }
-      if (platform === 'darwin' || platform === 'win32') assert(errThrown)
-      if (platform === 'linux') {
-        assert(fs.existsSync(dest))
-        assert.strictEqual(fs.readFileSync(path.join(dest, 'subdir', 'file.txt'), 'utf8'), 'some data')
-        assert(!errThrown)
-      }
+      fs.moveSync(src, dest)
+      assert(fs.existsSync(dest))
+      assert.strictEqual(fs.readFileSync(path.join(dest, 'subdir', 'file.txt'), 'utf8'), 'some data')
     })
   })
 
   describe('> when src is a file', () => {
-    it('should behave correctly based on the OS', () => {
+    it('should move successfully', () => {
       src = path.join(TEST_DIR, 'srcfile')
       fs.outputFileSync(src, 'some data')
       dest = path.join(TEST_DIR, 'srcFile')
-      let errThrown = false
 
-      try {
-        fs.moveSync(src, dest)
-      } catch (err) {
-        if (platform === 'darwin' || platform === 'win32') {
-          assert.strictEqual(err.message, 'Source and destination must not be the same.')
-          errThrown = true
-        }
-      }
-      if (platform === 'darwin' || platform === 'win32') assert(errThrown)
-      if (platform === 'linux') {
-        assert(fs.existsSync(dest))
-        assert.strictEqual(fs.readFileSync(dest, 'utf8'), 'some data')
-        assert(!errThrown)
-      }
+      fs.moveSync(src, dest)
+      assert(fs.existsSync(dest))
+      assert.strictEqual(fs.readFileSync(dest, 'utf8'), 'some data')
     })
   })
 
   describe('> when src is a symlink', () => {
-    it('should behave correctly based on the OS, symlink dir', () => {
+    it('should move successfully, symlink dir', () => {
       src = path.join(TEST_DIR, 'srcdir')
       fs.outputFileSync(path.join(src, 'subdir', 'file.txt'), 'some data')
       const srcLink = path.join(TEST_DIR, 'src-symlink')
       fs.symlinkSync(src, srcLink, 'dir')
       dest = path.join(TEST_DIR, 'src-Symlink')
-      let errThrown = false
 
-      try {
-        fs.moveSync(srcLink, dest)
-      } catch (err) {
-        if (platform === 'darwin' || platform === 'win32') {
-          assert.strictEqual(err.message, 'Source and destination must not be the same.')
-          errThrown = true
-        }
-      }
-      if (platform === 'darwin' || platform === 'win32') assert(errThrown)
-      if (platform === 'linux') {
-        assert(fs.existsSync(dest))
-        assert.strictEqual(fs.readFileSync(path.join(dest, 'subdir', 'file.txt'), 'utf8'), 'some data')
-        const destLink = fs.readlinkSync(dest)
-        assert.strictEqual(destLink, src)
-        assert(!errThrown)
-      }
+      fs.moveSync(srcLink, dest)
+      assert(fs.existsSync(dest))
+      assert.strictEqual(fs.readFileSync(path.join(dest, 'subdir', 'file.txt'), 'utf8'), 'some data')
+      const destLink = fs.readlinkSync(dest)
+      assert.strictEqual(destLink, src)
     })
 
-    it('should behave correctly based on the OS, symlink file', () => {
+    it('should move successfully, symlink file', () => {
       src = path.join(TEST_DIR, 'srcfile')
       fs.outputFileSync(src, 'some data')
       const srcLink = path.join(TEST_DIR, 'src-symlink')
       fs.symlinkSync(src, srcLink, 'file')
       dest = path.join(TEST_DIR, 'src-Symlink')
-      let errThrown = false
 
-      try {
-        fs.moveSync(srcLink, dest)
-      } catch (err) {
-        if (platform === 'darwin' || platform === 'win32') {
-          assert.strictEqual(err.message, 'Source and destination must not be the same.')
-          errThrown = true
-        }
-      }
-      if (platform === 'darwin' || platform === 'win32') assert(errThrown)
-      if (platform === 'linux') {
-        assert(fs.existsSync(dest))
-        assert.strictEqual(fs.readFileSync(dest, 'utf8'), 'some data')
-        const destLink = fs.readlinkSync(dest)
-        assert.strictEqual(destLink, src)
-        assert(!errThrown)
-      }
+      fs.moveSync(srcLink, dest)
+      assert(fs.existsSync(dest))
+      assert.strictEqual(fs.readFileSync(dest, 'utf8'), 'some data')
+      const destLink = fs.readlinkSync(dest)
+      assert.strictEqual(destLink, src)
     })
   })
 })
diff --git a/lib/move-sync/__tests__/move-sync-prevent-moving-identical.test.js b/lib/move-sync/__tests__/move-sync-prevent-moving-identical.test.js
index aed8acd..343586a 100644
--- a/lib/move-sync/__tests__/move-sync-prevent-moving-identical.test.js
+++ b/lib/move-sync/__tests__/move-sync-prevent-moving-identical.test.js
@@ -113,7 +113,7 @@ describe('+ moveSync() - prevent moving identical files and dirs', () => {
 
   describe('> when src is a directory', () => {
     describe('>> when src is regular and dest is a symlink that points to src', () => {
-      it('should error', () => {
+      it('should error if dereferene is true', () => {
         src = path.join(TEST_DIR, 'src')
         fs.mkdirsSync(src)
         const subdir = path.join(TEST_DIR, 'src', 'subdir')
@@ -126,7 +126,7 @@ describe('+ moveSync() - prevent moving identical files and dirs', () => {
         const oldlen = klawSync(src).length
 
         try {
-          fs.moveSync(src, destLink)
+          fs.moveSync(src, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
         }
@@ -166,7 +166,7 @@ describe('+ moveSync() - prevent moving identical files and dirs', () => {
     })
 
     describe('>> when src and dest are symlinks that point to the exact same path', () => {
-      it('should error src and dest are the same', () => {
+      it('should error if src and dest are the same and dereference is true', () => {
         src = path.join(TEST_DIR, 'src')
         fs.mkdirsSync(src)
         const srcLink = path.join(TEST_DIR, 'src_symlink')
@@ -178,7 +178,7 @@ describe('+ moveSync() - prevent moving identical files and dirs', () => {
         const destlenBefore = klawSync(destLink).length
 
         try {
-          fs.moveSync(srcLink, destLink)
+          fs.moveSync(srcLink, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
         }
@@ -203,7 +203,7 @@ describe('+ moveSync() - prevent moving identical files and dirs', () => {
 
   describe('> when src is a file', () => {
     describe('>> when src is regular and dest is a symlink that points to src', () => {
-      it('should error', () => {
+      it('should error if dereference is true', () => {
         src = path.join(TEST_DIR, 'src', 'somefile.txt')
         fs.ensureFileSync(src)
         fs.writeFileSync(src, 'some data')
@@ -212,7 +212,7 @@ describe('+ moveSync() - prevent moving identical files and dirs', () => {
         fs.symlinkSync(src, destLink, 'file')
 
         try {
-          fs.moveSync(src, destLink)
+          fs.moveSync(src, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
         }
@@ -243,7 +243,7 @@ describe('+ moveSync() - prevent moving identical files and dirs', () => {
     })
 
     describe('>> when src and dest are symlinks that point to the exact same path', () => {
-      it('should error src and dest are the same', () => {
+      it('should error if src and dest are the same and dereference is true', () => {
         src = path.join(TEST_DIR, 'src', 'srcfile.txt')
         fs.outputFileSync(src, 'src data')
 
@@ -254,7 +254,7 @@ describe('+ moveSync() - prevent moving identical files and dirs', () => {
         fs.symlinkSync(src, destLink, 'file')
 
         try {
-          fs.moveSync(srcLink, destLink)
+          fs.moveSync(srcLink, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
         }
diff --git a/lib/move-sync/__tests__/move-sync-prevent-moving-into-itself.test.js b/lib/move-sync/__tests__/move-sync-prevent-moving-into-itself.test.js
index dc2c759..ba31f92 100644
--- a/lib/move-sync/__tests__/move-sync-prevent-moving-into-itself.test.js
+++ b/lib/move-sync/__tests__/move-sync-prevent-moving-into-itself.test.js
@@ -167,7 +167,7 @@ describe('+ moveSync() - prevent moving into itself', () => {
     })
 
     describe('>> when dest is a symlink', () => {
-      it('should error when dest points exactly to src', () => {
+      it('should error when dest points exactly to src and dereference is true', () => {
         const destLink = path.join(TEST_DIR, 'dest-symlink')
         fs.symlinkSync(src, destLink, 'dir')
 
@@ -175,7 +175,7 @@ describe('+ moveSync() - prevent moving into itself', () => {
         assert(srclenBefore > 2)
         let errThrown = false
         try {
-          fs.moveSync(src, destLink)
+          fs.moveSync(src, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
           errThrown = true
@@ -321,7 +321,7 @@ describe('+ moveSync() - prevent moving into itself', () => {
     })
 
     describe('>> when dest is a symlink', () => {
-      it('should error when resolved dest path is exactly the same as resolved src path', () => {
+      it('should error when resolved dest path is exactly the same as resolved src path and dereferene is true', () => {
         const srcLink = path.join(TEST_DIR, 'src-symlink')
         fs.symlinkSync(src, srcLink, 'dir')
         const destLink = path.join(TEST_DIR, 'dest-symlink')
@@ -333,7 +333,7 @@ describe('+ moveSync() - prevent moving into itself', () => {
         assert(destlenBefore > 2)
         let errThrown = false
         try {
-          fs.moveSync(srcLink, destLink)
+          fs.moveSync(srcLink, destLink, { dereference: true })
         } catch (err) {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
           errThrown = true
diff --git a/lib/move/__tests__/move-case-insensitive-paths.test.js b/lib/move/__tests__/move-case-insensitive-paths.test.js
index 3076324..3e85f11 100644
--- a/lib/move/__tests__/move-case-insensitive-paths.test.js
+++ b/lib/move/__tests__/move-case-insensitive-paths.test.js
@@ -4,7 +4,6 @@ const assert = require('assert')
 const os = require('os')
 const path = require('path')
 const fs = require('../../')
-const platform = os.platform()
 
 /* global beforeEach, afterEach, describe, it */
 
@@ -21,47 +20,37 @@ describe('+ move() - case insensitive paths', () => {
   afterEach(done => fs.remove(TEST_DIR, done))
 
   describe('> when src is a directory', () => {
-    it('should behave correctly based on the OS', done => {
+    it('should move successfully', done => {
       src = path.join(TEST_DIR, 'srcdir')
       fs.outputFileSync(path.join(src, 'subdir', 'file.txt'), 'some data')
       dest = path.join(TEST_DIR, 'srcDir')
 
       fs.move(src, dest, err => {
-        if (platform === 'linux') {
-          assert.ifError(err)
-          assert(fs.existsSync(dest))
-          assert.strictEqual(fs.readFileSync(path.join(dest, 'subdir', 'file.txt'), 'utf8'), 'some data')
-        }
-        if (platform === 'darwin' || platform === 'win32') {
-          assert.strictEqual(err.message, 'Source and destination must not be the same.')
-        }
+        assert.ifError(err)
+        assert(fs.existsSync(dest))
+        assert.strictEqual(fs.readFileSync(path.join(dest, 'subdir', 'file.txt'), 'utf8'), 'some data')
         done()
       })
     })
   })
 
   describe('> when src is a file', () => {
-    it('should behave correctly based on the OS', done => {
+    it('should move successfully', done => {
       src = path.join(TEST_DIR, 'srcfile')
       fs.outputFileSync(src, 'some data')
       dest = path.join(TEST_DIR, 'srcFile')
 
       fs.move(src, dest, err => {
-        if (platform === 'linux') {
-          assert.ifError(err)
-          assert(fs.existsSync(dest))
-          assert.strictEqual(fs.readFileSync(dest, 'utf8'), 'some data')
-        }
-        if (platform === 'darwin' || platform === 'win32') {
-          assert.strictEqual(err.message, 'Source and destination must not be the same.')
-        }
+        assert.ifError(err)
+        assert(fs.existsSync(dest))
+        assert.strictEqual(fs.readFileSync(dest, 'utf8'), 'some data')
         done()
       })
     })
   })
 
   describe('> when src is a symlink', () => {
-    it('should behave correctly based on the OS, symlink dir', done => {
+    it('should move successfully, symlink dir', done => {
       src = path.join(TEST_DIR, 'srcdir')
       fs.outputFileSync(path.join(src, 'subdir', 'file.txt'), 'some data')
       const srcLink = path.join(TEST_DIR, 'src-symlink')
@@ -69,21 +58,16 @@ describe('+ move() - case insensitive paths', () => {
       dest = path.join(TEST_DIR, 'src-Symlink')
 
       fs.move(srcLink, dest, err => {
-        if (platform === 'linux') {
-          assert.ifError(err)
-          assert(fs.existsSync(dest))
-          assert.strictEqual(fs.readFileSync(path.join(dest, 'subdir', 'file.txt'), 'utf8'), 'some data')
-          const destLink = fs.readlinkSync(dest)
-          assert.strictEqual(destLink, src)
-        }
-        if (platform === 'darwin' || platform === 'win32') {
-          assert.strictEqual(err.message, 'Source and destination must not be the same.')
-        }
+        assert.ifError(err)
+        assert(fs.existsSync(dest))
+        assert.strictEqual(fs.readFileSync(path.join(dest, 'subdir', 'file.txt'), 'utf8'), 'some data')
+        const destLink = fs.readlinkSync(dest)
+        assert.strictEqual(destLink, src)
         done()
       })
     })
 
-    it('should behave correctly based on the OS, symlink file', done => {
+    it('should move successfully, symlink file', done => {
       src = path.join(TEST_DIR, 'srcfile')
       fs.outputFileSync(src, 'some data')
       const srcLink = path.join(TEST_DIR, 'src-symlink')
@@ -91,16 +75,11 @@ describe('+ move() - case insensitive paths', () => {
       dest = path.join(TEST_DIR, 'src-Symlink')
 
       fs.move(srcLink, dest, err => {
-        if (platform === 'linux') {
-          assert.ifError(err)
-          assert(fs.existsSync(dest))
-          assert.strictEqual(fs.readFileSync(dest, 'utf8'), 'some data')
-          const destLink = fs.readlinkSync(dest)
-          assert.strictEqual(destLink, src)
-        }
-        if (platform === 'darwin' || platform === 'win32') {
-          assert.strictEqual(err.message, 'Source and destination must not be the same.')
-        }
+        assert.ifError(err)
+        assert(fs.existsSync(dest))
+        assert.strictEqual(fs.readFileSync(dest, 'utf8'), 'some data')
+        const destLink = fs.readlinkSync(dest)
+        assert.strictEqual(destLink, src)
         done()
       })
     })
diff --git a/lib/move/__tests__/move-prevent-moving-identical.test.js b/lib/move/__tests__/move-prevent-moving-identical.test.js
index 840ab00..c2d4a16 100644
--- a/lib/move/__tests__/move-prevent-moving-identical.test.js
+++ b/lib/move/__tests__/move-prevent-moving-identical.test.js
@@ -104,7 +104,7 @@ describe('+ move() - prevent moving identical files and dirs', () => {
 
   describe('> when src is a directory', () => {
     describe('>> when src is regular and dest is a symlink that points to src', () => {
-      it('should error', done => {
+      it('should error if dereference is true', done => {
         src = path.join(TEST_DIR, 'src')
         fs.mkdirsSync(src)
         const subdir = path.join(TEST_DIR, 'src', 'subdir')
@@ -116,7 +116,7 @@ describe('+ move() - prevent moving identical files and dirs', () => {
 
         const oldlen = klawSync(src).length
 
-        fs.move(src, destLink, err => {
+        fs.move(src, destLink, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
 
           const newlen = klawSync(src).length
@@ -155,7 +155,7 @@ describe('+ move() - prevent moving identical files and dirs', () => {
     })
 
     describe('>> when src and dest are symlinks that point to the exact same path', () => {
-      it('should error src and dest are the same', done => {
+      it('should error src and dest are the same and dereference is true', done => {
         src = path.join(TEST_DIR, 'src')
         fs.mkdirsSync(src)
         const srcLink = path.join(TEST_DIR, 'src_symlink')
@@ -166,7 +166,7 @@ describe('+ move() - prevent moving identical files and dirs', () => {
         const srclenBefore = klawSync(srcLink).length
         const destlenBefore = klawSync(destLink).length
 
-        fs.move(srcLink, destLink, err => {
+        fs.move(srcLink, destLink, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
 
           const srclenAfter = klawSync(srcLink).length
@@ -191,14 +191,14 @@ describe('+ move() - prevent moving identical files and dirs', () => {
 
   describe('> when src is a file', () => {
     describe('>> when src is regular and dest is a symlink that points to src', () => {
-      it('should error', done => {
+      it('should error if dereference is true', done => {
         src = path.join(TEST_DIR, 'src.txt')
         fs.outputFileSync(src, 'some data')
 
         const destLink = path.join(TEST_DIR, 'dest-symlink')
         fs.symlinkSync(src, destLink, 'file')
 
-        fs.move(src, destLink, err => {
+        fs.move(src, destLink, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
           done()
         })
@@ -206,14 +206,14 @@ describe('+ move() - prevent moving identical files and dirs', () => {
     })
 
     describe('>> when src is a symlink that points to a regular dest', () => {
-      it('should throw error', done => {
+      it('should throw error if dereferene is true', done => {
         dest = path.join(TEST_DIR, 'dest', 'somefile.txt')
         fs.outputFileSync(dest, 'some data')
 
         const srcLink = path.join(TEST_DIR, 'src-symlink')
         fs.symlinkSync(dest, srcLink, 'file')
 
-        fs.move(srcLink, dest, err => {
+        fs.move(srcLink, dest, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
 
           const link = fs.readlinkSync(srcLink)
@@ -225,7 +225,7 @@ describe('+ move() - prevent moving identical files and dirs', () => {
     })
 
     describe('>> when src and dest are symlinks that point to the exact same path', () => {
-      it('should error src and dest are the same', done => {
+      it('should error src and dest are the same and dereferene is true', done => {
         src = path.join(TEST_DIR, 'src', 'srcfile.txt')
         fs.outputFileSync(src, 'src data')
 
@@ -235,7 +235,7 @@ describe('+ move() - prevent moving identical files and dirs', () => {
         const destLink = path.join(TEST_DIR, 'dest_symlink')
         fs.symlinkSync(src, destLink, 'file')
 
-        fs.move(srcLink, destLink, err => {
+        fs.move(srcLink, destLink, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
 
           const srcln = fs.readlinkSync(srcLink)
diff --git a/lib/move/__tests__/move-prevent-moving-into-itself.test.js b/lib/move/__tests__/move-prevent-moving-into-itself.test.js
index d24aed6..f40eba3 100644
--- a/lib/move/__tests__/move-prevent-moving-into-itself.test.js
+++ b/lib/move/__tests__/move-prevent-moving-into-itself.test.js
@@ -52,9 +52,6 @@ describe('+ move() - prevent moving into itself', () => {
         done()
       })
     })
-  })
-
-  describe('> when source is a file', () => {
     it("should move the file successfully even when dest parent is 'src/dest'", done => {
       const destFile = path.join(TEST_DIR, 'src', 'dest', 'destfile.txt')
       return testSuccessFile(src, destFile, done)
@@ -169,25 +166,6 @@ describe('+ move() - prevent moving into itself', () => {
     })
 
     describe('>> when dest is a symlink', () => {
-      it('should error when dest points exactly to src', done => {
-        const destLink = path.join(TEST_DIR, 'dest-symlink')
-        fs.symlinkSync(src, destLink, 'dir')
-
-        const srclenBefore = klawSync(src).length
-        assert(srclenBefore > 2)
-
-        fs.move(src, destLink, err => {
-          assert.strictEqual(err.message, 'Source and destination must not be the same.')
-
-          const srclenAfter = klawSync(src).length
-          assert.strictEqual(srclenAfter, srclenBefore, 'src length should not change')
-
-          const link = fs.readlinkSync(destLink)
-          assert.strictEqual(link, src)
-          done()
-        })
-      })
-
       it('should error when dest is a subdirectory of src (bind-mounted directory with subdirectory)', done => {
         const destLink = path.join(TEST_DIR, 'dest-symlink')
         fs.symlinkSync(src, destLink, 'dir')
@@ -306,7 +284,7 @@ describe('+ move() - prevent moving into itself', () => {
     })
 
     describe('>> when dest is a symlink', () => {
-      it('should error when resolved dest path is exactly the same as resolved src path', done => {
+      it('should error when resolved dest path is exactly the same as resolved src path and dereferene is true', done => {
         const srcLink = path.join(TEST_DIR, 'src-symlink')
         fs.symlinkSync(src, srcLink, 'dir')
         const destLink = path.join(TEST_DIR, 'dest-symlink')
@@ -317,7 +295,7 @@ describe('+ move() - prevent moving into itself', () => {
         assert(srclenBefore > 2)
         assert(destlenBefore > 2)
 
-        fs.move(srcLink, destLink, err => {
+        fs.move(srcLink, destLink, { dereference: true }, err => {
           assert.strictEqual(err.message, 'Source and destination must not be the same.')
 
           const srclenAfter = klawSync(srcLink).length
diff --git a/lib/util/__tests__/stat.test.js b/lib/util/__tests__/stat.test.js
index 8d0e85d..2b7de64 100644
--- a/lib/util/__tests__/stat.test.js
+++ b/lib/util/__tests__/stat.test.js
@@ -27,7 +27,7 @@ describe('util/stat', () => {
       const dest = path.join(TEST_DIR, 'dest')
       fs.ensureFileSync(src)
       fs.ensureFileSync(dest)
-      stat.checkPaths(src, dest, 'copy', (err, stats) => {
+      stat.checkPaths(src, dest, 'copy', {}, (err, stats) => {
         assert.ifError(err)
         const { srcStat } = stats
         if (atLeastNode(NODE_VERSION_WITH_BIGINT)) {
@@ -43,7 +43,7 @@ describe('util/stat', () => {
       const dest = path.join(TEST_DIR, 'dest')
       fs.ensureFileSync(src)
       fs.ensureFileSync(dest)
-      const { srcStat } = stat.checkPathsSync(src, dest, 'copy')
+      const { srcStat } = stat.checkPathsSync(src, dest, 'copy', {})
       if (atLeastNode(NODE_VERSION_WITH_BIGINT)) {
         assert.strictEqual(typeof srcStat.ino, 'bigint')
       } else {