node-fs-extra/lib/move-sync/__tests__/move-sync.test.js
Ryan Zimmerman 20c82ab4dd
Run stricter linter to cleanup problems and force ES6 usage (#566)
Also shorten fs.write() promise code
2018-04-10 08:12:12 -04:00

354 lines
10 KiB
JavaScript

'use strict'
const fs = require('graceful-fs')
const os = require('os')
const fse = require(process.cwd())
const path = require('path')
const assert = require('assert')
const rimraf = require('rimraf')
/* global afterEach, beforeEach, describe, it */
function createSyncErrFn (errCode) {
const fn = function () {
const err = new Error()
err.code = errCode
throw err
}
return fn
}
const originalRenameSync = fs.renameSync
const originalLinkSync = fs.linkSync
function setUpMockFs (errCode) {
fs.renameSync = createSyncErrFn(errCode)
fs.linkSync = createSyncErrFn(errCode)
}
function tearDownMockFs () {
fs.renameSync = originalRenameSync
fs.linkSync = originalLinkSync
}
describe('moveSync()', () => {
let TEST_DIR
beforeEach(() => {
TEST_DIR = path.join(os.tmpdir(), 'fs-extra', 'move-sync')
fse.emptyDirSync(TEST_DIR)
// Create fixtures:
fs.writeFileSync(path.join(TEST_DIR, 'a-file'), 'sonic the hedgehog\n')
fs.mkdirSync(path.join(TEST_DIR, 'a-folder'))
fs.writeFileSync(path.join(TEST_DIR, 'a-folder/another-file'), 'tails\n')
fs.mkdirSync(path.join(TEST_DIR, 'a-folder/another-folder'))
fs.writeFileSync(path.join(TEST_DIR, 'a-folder/another-folder/file3'), 'knuckles\n')
})
afterEach(done => rimraf(TEST_DIR, done))
it('should not move if src and dest are the same', () => {
const src = `${TEST_DIR}/a-file`
const dest = `${TEST_DIR}/a-file`
fse.moveSync(src, dest)
// assert src not affected
const contents = fs.readFileSync(src, 'utf8')
const expected = /^sonic the hedgehog\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
})
it('should error if src and dest are the same and src does not exist', () => {
const src = `${TEST_DIR}/non-existent`
const dest = src
assert.throws(() => fse.moveSync(src, dest))
})
it('should rename a file on the same device', () => {
const src = `${TEST_DIR}/a-file`
const dest = `${TEST_DIR}/a-file-dest`
fse.moveSync(src, dest)
const contents = fs.readFileSync(dest, 'utf8')
const expected = /^sonic the hedgehog\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
})
it('should not overwrite the destination by default', () => {
const src = `${TEST_DIR}/a-file`
const dest = `${TEST_DIR}/a-folder/another-file`
// verify file exists already
assert(fs.existsSync(dest))
try {
fse.moveSync(src, dest)
} catch (err) {
assert.ok(err && err.code === 'EEXIST', 'throw EEXIST')
}
})
it('should not overwrite if overwrite = false', () => {
const src = `${TEST_DIR}/a-file`
const dest = `${TEST_DIR}/a-folder/another-file`
// verify file exists already
assert(fs.existsSync(dest))
try {
fse.moveSync(src, dest, {overwrite: false})
} catch (err) {
assert.ok(err && err.code === 'EEXIST', 'throw EEXIST')
}
})
it('should overwrite file if overwrite = true', () => {
const src = `${TEST_DIR}/a-file`
const dest = `${TEST_DIR}/a-folder/another-file`
// verify file exists already
assert(fs.existsSync(dest))
fse.moveSync(src, dest, {overwrite: true})
const contents = fs.readFileSync(dest, 'utf8')
const expected = /^sonic the hedgehog\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
})
it('should overwrite the destination directory if overwrite = true', done => {
// Create src
const src = path.join(TEST_DIR, 'src')
fse.ensureDirSync(src)
fse.mkdirsSync(path.join(src, 'some-folder'))
fs.writeFileSync(path.join(src, 'some-file'), 'hi')
const dest = path.join(TEST_DIR, 'a-folder')
// verify dest has stuff in it
const pathsBefore = fs.readdirSync(dest)
assert(pathsBefore.indexOf('another-file') >= 0)
assert(pathsBefore.indexOf('another-folder') >= 0)
fse.moveSync(src, dest, {overwrite: true})
// verify dest does not have old stuff
const pathsAfter = fs.readdirSync(dest)
assert.strictEqual(pathsAfter.indexOf('another-file'), -1)
assert.strictEqual(pathsAfter.indexOf('another-folder'), -1)
// verify dest has new stuff
assert(pathsAfter.indexOf('some-file') >= 0)
assert(pathsAfter.indexOf('some-folder') >= 0)
done()
})
it('should create directory structure by default', () => {
const src = `${TEST_DIR}/a-file`
const dest = `${TEST_DIR}/does/not/exist/a-file-dest`
// verify dest directory does not exist
assert(!fs.existsSync(path.dirname(dest)))
fse.moveSync(src, dest)
const contents = fs.readFileSync(dest, 'utf8')
const expected = /^sonic the hedgehog\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
})
it('should work across devices', () => {
const src = `${TEST_DIR}/a-file`
const dest = `${TEST_DIR}/a-file-dest`
setUpMockFs('EXDEV')
fse.moveSync(src, dest)
const contents = fs.readFileSync(dest, 'utf8')
const expected = /^sonic the hedgehog\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
tearDownMockFs()
})
it('should move folders', () => {
const src = `${TEST_DIR}/a-folder`
const dest = `${TEST_DIR}/a-folder-dest`
// verify it doesn't exist
assert(!fs.existsSync(dest))
fse.moveSync(src, dest)
const contents = fs.readFileSync(dest + '/another-file', 'utf8')
const expected = /^tails\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
})
it('should move folders across devices with EISDIR error', () => {
const src = `${TEST_DIR}/a-folder`
const dest = `${TEST_DIR}/a-folder-dest`
setUpMockFs('EISDIR')
fse.moveSync(src, dest)
const contents = fs.readFileSync(dest + '/another-folder/file3', 'utf8')
const expected = /^knuckles\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
tearDownMockFs()
})
it('should overwrite folders across devices', () => {
const src = `${TEST_DIR}/a-folder`
const dest = `${TEST_DIR}/a-folder-dest`
fs.mkdirSync(dest)
setUpMockFs('EXDEV')
fse.moveSync(src, dest, {overwrite: true})
const contents = fs.readFileSync(dest + '/another-folder/file3', 'utf8')
const expected = /^knuckles\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
tearDownMockFs()
})
it('should move folders across devices with EXDEV error', () => {
const src = `${TEST_DIR}/a-folder`
const dest = `${TEST_DIR}/a-folder-dest`
setUpMockFs('EXDEV')
fse.moveSync(src, dest)
const contents = fs.readFileSync(dest + '/another-folder/file3', 'utf8')
const expected = /^knuckles\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
tearDownMockFs()
})
it('should move folders across devices with EPERM error', () => {
const src = `${TEST_DIR}/a-folder`
const dest = `${TEST_DIR}/a-folder-dest`
setUpMockFs('EPERM')
fse.moveSync(src, dest)
const contents = fs.readFileSync(dest + '/another-folder/file3', 'utf8')
const expected = /^knuckles\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
tearDownMockFs()
})
it('should move folders across devices with ENOTSUP error', () => {
const src = `${TEST_DIR}/a-folder`
const dest = `${TEST_DIR}/a-folder-dest`
setUpMockFs('ENOTSUP')
fse.moveSync(src, dest)
const contents = fs.readFileSync(dest + '/another-folder/file3', 'utf8')
const expected = /^knuckles\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
tearDownMockFs()
})
describe('clobber', () => {
it('should be an alias for overwrite', () => {
const src = `${TEST_DIR}/a-file`
const dest = `${TEST_DIR}/a-folder/another-file`
// verify file exists already
assert(fs.existsSync(dest))
fse.moveSync(src, dest, {clobber: true})
const contents = fs.readFileSync(dest, 'utf8')
const expected = /^sonic the hedgehog\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
})
})
describe('> when trying to move a folder into itself', () => {
it('should produce an error', () => {
const SRC_DIR = path.join(TEST_DIR, 'src')
const DEST_DIR = path.join(TEST_DIR, 'src', 'dest')
assert(!fs.existsSync(SRC_DIR))
fs.mkdirSync(SRC_DIR)
assert(fs.existsSync(SRC_DIR))
try {
fse.moveSync(SRC_DIR, DEST_DIR)
} catch (err) {
assert(err.message, `Cannot move ${SRC_DIR} into itself ${DEST_DIR}.`)
assert(fs.existsSync(SRC_DIR))
assert(!fs.existsSync(DEST_DIR))
}
})
})
describe('> when trying to move a file into its parent subdirectory', () => {
it('should move successfully', () => {
const src = `${TEST_DIR}/a-file`
const dest = `${TEST_DIR}/dest/a-file-dest`
fse.moveSync(src, dest)
const contents = fs.readFileSync(dest, 'utf8')
const expected = /^sonic the hedgehog\r?\n$/
assert.ok(contents.match(expected), `${contents} match ${expected}`)
})
})
describe('> when actually trying to move a folder across devices', () => {
const differentDevice = '/mnt'
let __skipTests = false
// must set this up, if not, exit silently
if (!fs.existsSync(differentDevice)) {
console.log('Skipping cross-device moveSync test')
__skipTests = true
}
// make sure we have permission on device
try {
fs.writeFileSync(path.join(differentDevice, 'file'), 'hi')
} catch (err) {
console.log("Can't write to device. Skipping moveSync test.")
__skipTests = true
}
const _it = __skipTests ? it.skip : it
describe('> just the folder', () => {
_it('should move the folder', () => {
const src = '/mnt/some/weird/dir-really-weird'
const dest = path.join(TEST_DIR, 'device-weird')
if (!fs.existsSync(src)) {
fse.mkdirpSync(src)
}
assert(!fs.existsSync(dest))
assert(fs.lstatSync(src).isDirectory())
fse.moveSync(src, dest)
assert(fs.existsSync(dest))
assert(fs.lstatSync(dest).isDirectory())
})
})
})
})