macOS's Weird Temporary Directory
On a project, you might want to create a bunch of temporary directories to run tests against. It's a great way to isolate test cases that share the same fixture. Some of these tests might assert on a file path within these directories.
const testDirPath = path.resolve(os.tmpdir(), "test-");
const testDir = await fs.mkdtemp(testDirPath);
await copy(fixtureDir, testDir);
const result = doSomething(testDir);
const expected = path.resolve(testDir, "expected-file.txt");
expect(result).toEqual(expected);
That's all fine on Windows and Linux.
Note: For brevity, I've shortened some of the randomly generated characters.
result = "/tmp/test-dv2s/expected-file.txt";
expected = "/tmp/test-dv2s/expected-file.txt";
But on macOS, something weird happens.
result = "/private/var/folders/a2/cxod_f8ou3/T/test-dv2s/expected-file.txt";
expected = "/var/folders/a2/cxod_f8ou3/T/test-dv2s/expected-file.txt";
What's up with the /private
? To resolve these sorts of path mismatches, having realpath
in your terminal helps. It's a pretty common tool on Linux. macOS doesn't ship with it but it's easy to install via Homebrew.
brew install coreutils
Now let's check our expected path.
$ realpath /var/folders/a2/cxod_f8ou3/T/test-dv2s/expected-file.txt
/private/var/folders/a2/cxod_f8ou3/T/test-dv2s/expected-file.txt
So macOS seems to do some stuff to isolate temporary files. Probably a security thing. Now that we know that, we should resolve any paths within temporary directories to real paths.
const testDirPath = path.resolve(os.tmpdir(), "test-");
const testDirTemp = await fs.mkdtemp(testDirPath);
const testDir = await fs.realpath(testDirTemp); // new step
And it works!
result = "/private/var/folders/a2/cxod_f8ou3/T/test-dv2s/expected-file.txt";
expected = "/private/var/folders/a2/cxod_f8ou3/T/test-dv2s/expected-file.txt";
Let's simplify this setup so that we don't have to worry about what's real and what isn't.
const createTempDir = async (dirName: string): Promise<string> => {
return fs.realpath(
await fs.mkdtemp(path.resolve(os.tmpdir(), `${dirName}-`))
);
};
Now we can call a single function.
const testDir = await createTempDir("test");
Thanks for reading.