|
| 1 | +import assert from "node:assert/strict"; |
| 2 | +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; |
| 3 | +import { tmpdir } from "node:os"; |
| 4 | +import { dirname, join } from "node:path"; |
| 5 | +import { test } from "node:test"; |
| 6 | +import { optedOut } from "./telemetry.mjs"; |
| 7 | + |
| 8 | +// optedOut() reads ~/.hyperframes/config.json and env vars. Point HOME at a temp |
| 9 | +// dir so the run never touches the real config, and pin the env opt-outs to a |
| 10 | +// neutral state; restore both afterwards. |
| 11 | +const ENV_KEYS = [ |
| 12 | + "HOME", |
| 13 | + "USERPROFILE", |
| 14 | + "HYPERFRAMES_NO_TELEMETRY", |
| 15 | + "DO_NOT_TRACK", |
| 16 | + "CI", |
| 17 | + "NODE_ENV", |
| 18 | +]; |
| 19 | +const savedEnv = Object.fromEntries(ENV_KEYS.map((k) => [k, process.env[k]])); |
| 20 | +const home = mkdtempSync(join(tmpdir(), "mu-telemetry-")); |
| 21 | +const configPath = join(home, ".hyperframes", "config.json"); |
| 22 | + |
| 23 | +function writeConfig(contents) { |
| 24 | + if (contents === null) { |
| 25 | + rmSync(configPath, { force: true }); |
| 26 | + } else { |
| 27 | + mkdirSync(dirname(configPath), { recursive: true }); |
| 28 | + writeFileSync(configPath, contents); |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +test.before(() => { |
| 33 | + for (const key of ENV_KEYS) delete process.env[key]; |
| 34 | + process.env.HOME = process.env.USERPROFILE = home; |
| 35 | +}); |
| 36 | + |
| 37 | +test.after(() => { |
| 38 | + for (const key of ENV_KEYS) { |
| 39 | + if (savedEnv[key] === undefined) delete process.env[key]; |
| 40 | + else process.env[key] = savedEnv[key]; |
| 41 | + } |
| 42 | + rmSync(home, { recursive: true, force: true }); |
| 43 | +}); |
| 44 | + |
| 45 | +test("optedOut is false with no config and no opt-out env", () => { |
| 46 | + writeConfig(null); |
| 47 | + assert.equal(optedOut(), false); |
| 48 | +}); |
| 49 | + |
| 50 | +test("optedOut honors telemetryEnabled: false from the shared config", () => { |
| 51 | + writeConfig(JSON.stringify({ telemetryEnabled: false })); |
| 52 | + assert.equal(optedOut(), true); |
| 53 | +}); |
| 54 | + |
| 55 | +test("optedOut is false when the shared config enables telemetry", () => { |
| 56 | + writeConfig(JSON.stringify({ telemetryEnabled: true })); |
| 57 | + assert.equal(optedOut(), false); |
| 58 | +}); |
| 59 | + |
| 60 | +test("optedOut treats an unreadable shared config as no opt-out", () => { |
| 61 | + writeConfig("{not json"); |
| 62 | + assert.equal(optedOut(), false); |
| 63 | +}); |
| 64 | + |
| 65 | +test("optedOut still honors the env opt-outs", () => { |
| 66 | + writeConfig(JSON.stringify({ telemetryEnabled: true })); |
| 67 | + process.env.DO_NOT_TRACK = "1"; |
| 68 | + try { |
| 69 | + assert.equal(optedOut(), true); |
| 70 | + } finally { |
| 71 | + delete process.env.DO_NOT_TRACK; |
| 72 | + } |
| 73 | +}); |
0 commit comments