diff --git a/test/90.service/90.github/fs-extra-createSymlink-bug.test.js b/test/90.service/90.github/fs-extra-createSymlink-bug.test.js new file mode 100644 index 00000000..e5d877d6 --- /dev/null +++ b/test/90.service/90.github/fs-extra-createSymlink-bug.test.js @@ -0,0 +1,63 @@ +/* eslint-env mocha */ + +require('should') +const { resolve, join, relative, dirname } = require('node:path') +const { ensureFile, remove, pathExists, ensureSymlink } = require('fs-extra') + +const testBaseDirectory = resolve('fs-extra-test-base-directory') + +/* MUDO submitted as https://github.com/jprichardson/node-fs-extra/issues/1038 */ + +describe('fs-extra ensureSymlink fails when ensuring a symbolic link with a relative path if it already exists', function () { + beforeEach(async function () { + // a directory with a file, as `destination` or `target` + this.targetDirectory = join(testBaseDirectory, 'target-directory') + const targetFileName = 'target-file' + this.targetDirectoryFile = join(this.targetDirectory, targetFileName) + await ensureFile(this.targetDirectoryFile) + // a directory to put the symbolic link in (the `source`) + this.linkDirectory = join(testBaseDirectory, 'link-directory') + this.symbolicLinkPath = join(this.linkDirectory, 'link') + this.targetFileViaSymbolicLink = join(this.symbolicLinkPath, targetFileName) + this.relativeSymbolicLinkReference = relative(dirname(this.symbolicLinkPath), this.targetDirectory) + }) + + afterEach(async function () { + return remove(testBaseDirectory) + }) + + it('can ensure a symbolic link a second time with an absolute path', async function () { + await pathExists(this.targetDirectoryFile).should.be.resolvedWith(true) + + // first time, setting up with a relative reference + await ensureSymlink(this.relativeSymbolicLinkReference, this.symbolicLinkPath, 'dir').should.be.resolved() + await pathExists(this.symbolicLinkPath).should.be.resolvedWith(true) + await pathExists(this.targetFileViaSymbolicLink).should.be.resolvedWith(true) + + // second time, setting up with an absolute reference + await ensureSymlink(this.targetDirectory, this.symbolicLinkPath, 'dir').should.be.resolved() + await pathExists(this.symbolicLinkPath).should.be.resolvedWith(true) + await pathExists(this.targetFileViaSymbolicLink).should.be.resolvedWith(true) + }) + + it('can ensure a symbolic link a second time with a relative path', async function () { + await pathExists(this.targetDirectoryFile).should.be.resolvedWith(true) + + // first time, setting up with a relative reference + await ensureSymlink(this.relativeSymbolicLinkReference, this.symbolicLinkPath, 'dir').should.be.resolved() + await pathExists(this.symbolicLinkPath).should.be.resolvedWith(true) + await pathExists(this.targetFileViaSymbolicLink).should.be.resolvedWith(true) + + // second time, setting up with a relative reference SHOULD ALSO RESOLVE, BUT REJECTS + const error = await ensureSymlink( + this.relativeSymbolicLinkReference, + this.symbolicLinkPath, + 'dir' + ).should.be.rejected() + error.code.should.equal('ENOENT') + // YET THE TARGET FILE EXISTS VIA THE ABSOLUTE PATH + await pathExists(this.targetDirectory).should.be.resolvedWith(true) + // AND THE RELATIVE PATH RESOLVES TO THE ABSOLUTE PATH + join(dirname(this.symbolicLinkPath), this.relativeSymbolicLinkReference).should.equal(this.targetDirectory) + }) +})