fix(test): resolve the macOS temp root through its symlink in the launcher and preview tests (#501)

Supersedes #301 by @VassagoDevteam, ported onto the current component layout with fixes from review.

Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.

Co-authored-by: Vassago DevTeam <[email protected]>
This commit is contained in:
Bilawal SidhuandVassago DevTeam authored and GitHub committed 2026-09-14 18:55:24 -05:00
1 parent c56ef52ce3
commit a1d0a42450
7 files changed
+99 -5

No files matched your search

+8
View File
@@ -273,6 +273,14 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md
### Development
- The CCTV launcher and preview-server tests resolve their temporary fixture
root through `fs.realpath`, so they pass on macOS, where the system temp
directory is reached through a symlink and the paths the tests compare would
otherwise differ. The launcher, preview-server and tool-project tests share one
helper that resolves the root, and a case that builds a symlinked temp root
explicitly keeps it covered on Linux, whose own temp root is not symlinked.
Contributed by VassagoDevteam (#301).
- Extract application lifecycle and viewer exports. Split standalone startup into
scene setup, controls, layer registration, tools and loading UI. Startup failure
and terminal shutdown release acquired resources and cancel delayed work.
+2
View File
@@ -7,6 +7,8 @@
"scripts/check-package-boundaries.mjs",
"scripts/precompute-cctv-heights.mjs",
"src/tooling/precomputeCctvHeights.test.mjs",
"src/tooling/fixtureRoot.mjs",
"src/tooling/fixtureRoot.test.mjs",
"src/tooling/format.test.mjs",
"src/tooling/packageBoundaries.test.mjs",
"src/data/infrastructure.js",
+4 -1
View File
@@ -6,12 +6,15 @@ import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
import { makeFixtureRoot } from './tooling/fixtureRoot.mjs';
const run = promisify(execFile);
const bashTest = process.platform === 'win32' ? test.skip : test;
async function launch(overrides = {}, dotenv = '', omitCctv = false) {
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'gev-cctv-launch-'));
// Physical path: the launched process reports its cwd resolved, and macOS
// reaches the temp directory through a symlink.
const root = await makeFixtureRoot('gev-cctv-launch-');
try {
await fs.mkdir(path.join(root, 'scripts'));
await fs.mkdir(path.join(root, 'bin'));
+4 -1
View File
@@ -8,6 +8,7 @@ import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
import { projectRoot } from '../scripts/project-root.mjs';
import { inspectSetup } from '../scripts/setup-doctor.mjs';
import { makeFixtureRoot } from './tooling/fixtureRoot.mjs';
const run = promisify(execFile);
const sourceRoot = fileURLToPath(new URL('../', import.meta.url));
@@ -60,7 +61,9 @@ const bashTest = process.platform === 'win32' ? test.skip : test;
bashTest(
'launcher reads the selected project keys and starts its command while source checks use the installation',
async () => {
const root = await mkdtemp(path.join(os.tmpdir(), 'gev other project-'));
// Physical path: the launched process reports its cwd resolved, and macOS
// reaches the temp directory through a symlink.
const root = await makeFixtureRoot('gev other project-');
try {
const bin = path.join(root, 'bin');
await mkdir(bin);
+21
View File
@@ -0,0 +1,21 @@
import { mkdtemp, realpath } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import path from 'node:path';
/**
* Create a temporary directory for a test fixture, resolved to its physical
* path.
*
* The system temp directory is reached through a symlink on macOS
* (`/var` -> `/private/var`, `/tmp` -> `/private/tmp`). A test that gives the
* logical path to something that reports paths back — a launched process's
* working directory, a bundler's project root — then compares two spellings of
* the same directory and fails. Resolving the root once, here, keeps both sides
* on the physical path.
*
* @param {string} prefix - Directory name prefix, e.g. `gev-preview-`.
* @returns {Promise<string>} The fixture root, with no symlinked component.
*/
export async function makeFixtureRoot(prefix) {
return realpath(await mkdtemp(path.join(tmpdir(), prefix)));
}
+55
View File
@@ -0,0 +1,55 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { mkdir, mkdtemp, realpath, rm, symlink } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import path from 'node:path';
import { makeFixtureRoot } from './fixtureRoot.mjs';
// Creating a symlink needs a privilege Windows does not grant by default, and
// Windows reads its temp directory from other variables than TMPDIR. The case
// therefore covers macOS and Linux; a Windows equivalent would have to build a
// directory junction and set TEMP.
const symlinkTest = process.platform === 'win32' ? test.skip : test;
symlinkTest(
'a fixture root is physical even when the temp root is a symlink',
async (t) => {
// macOS reaches its own temp directory through a symlink and Linux does
// not, so build one explicitly: without it this check would pass on the
// Linux runner while every Mac contributor still saw the failure it exists
// to prevent.
const scratch = await realpath(
await mkdtemp(path.join(tmpdir(), 'gev-fixture-root-')),
);
t.after(() => rm(scratch, { recursive: true, force: true }));
const physical = path.join(scratch, 'physical');
const viaLink = path.join(scratch, 'link');
await mkdir(physical);
await symlink(physical, viaLink);
const before = process.env.TMPDIR;
process.env.TMPDIR = viaLink;
t.after(() => {
if (before === undefined) delete process.env.TMPDIR;
else process.env.TMPDIR = before;
});
// Fail rather than pass vacuously: if the temp root is not the symlink,
// the condition under test was never set up.
assert.equal(
tmpdir(),
viaLink,
'the symlinked temp root was not in force, so nothing was exercised',
);
const root = await makeFixtureRoot('gev-fixture-case-');
assert.equal(
root,
await realpath(root),
'the fixture root still contains a symlink',
);
assert.ok(
root.startsWith(`${physical}${path.sep}`),
`${root} is not under the physical temp root ${physical}`,
);
},
);
+5 -3
View File
@@ -1,11 +1,11 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { mkdtemp, writeFile, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { writeFile, rm } from 'node:fs/promises';
import path from 'node:path';
import { build, createServer, preview } from 'vite';
import { localProviderPlugins } from '../../server/providers/local.js';
import { apiNotFoundPlugin } from '../../server/standalone/api-not-found.js';
import { makeFixtureRoot } from './fixtureRoot.mjs';
test('data providers have both hooks; credential editing stays development-only', () => {
for (const plugin of localProviderPlugins()) {
@@ -27,7 +27,9 @@ test('data providers have both hooks; credential editing stays development-only'
});
test('real dev and built-preview servers serve provider JSON and terminate unknown APIs', async (t) => {
const root = await mkdtemp(path.join(tmpdir(), 'gev-preview-'));
// Physical path: Vite's root and the files written under it must agree on one
// spelling, and macOS reaches the temp directory through a symlink.
const root = await makeFixtureRoot('gev-preview-');
t.after(() => rm(root, { recursive: true, force: true }));
await writeFile(
path.join(root, 'index.html'),