Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions tests/history-profile.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,88 @@ test('formatProfile renders dominant tone, capitalization, scope, body, and pref
assert.match(output, /Body usage: 50%/);
assert.match(output, /Common prefixes: fix: \(75%\), feat: \(25%\)/);
});

test('buildProfile computes scope-usage ratio', async () => {
const originalHome = process.env.HOME;

@cubic-dev-ai cubic-dev-ai Bot Aug 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The three new tests each repeat the same ~14-line environment setup/teardown block (saving HOME/APPDATA/XDG_CONFIG_HOME, creating a temp home, setting the three env vars, then restoring them and deleting the temp dir in finally). This boilerplate already appears three times earlier in the file, so it now exists six times. Consider extracting a small helper like withTempHome(async (tempHome) => { ... }) that owns the env save/set/restore and rmSync cleanup, and have each test call writeHistory and buildProfile inside it. This keeps the new tests focused on the ratio logic and avoids six copies of the same fragile env/teardown code.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/history-profile.test.mjs, line 199:

<comment>The three new tests each repeat the same ~14-line environment setup/teardown block (saving HOME/APPDATA/XDG_CONFIG_HOME, creating a temp home, setting the three env vars, then restoring them and deleting the temp dir in `finally`). This boilerplate already appears three times earlier in the file, so it now exists six times. Consider extracting a small helper like `withTempHome(async (tempHome) => { ... })` that owns the env save/set/restore and `rmSync` cleanup, and have each test call `writeHistory` and `buildProfile` inside it. This keeps the new tests focused on the ratio logic and avoids six copies of the same fragile env/teardown code.</comment>

<file context>
@@ -194,3 +194,88 @@ test('formatProfile renders dominant tone, capitalization, scope, body, and pref
 });
+
+test('buildProfile computes scope-usage ratio', async () => {
+  const originalHome = process.env.HOME;
+  const originalAppData = process.env.APPDATA;
+  const originalXdgConfigHome = process.env.XDG_CONFIG_HOME;
</file context>
Fix with cubic

const originalAppData = process.env.APPDATA;
const originalXdgConfigHome = process.env.XDG_CONFIG_HOME;
const tempHome = mkdtempSync(join(tmpdir(), 'commit-echo-home-'));

try {
process.env.HOME = tempHome;
process.env.APPDATA = join(tempHome, 'AppData', 'Roaming');
process.env.XDG_CONFIG_HOME = join(tempHome, '.config');
writeHistory(tempHome, [
'feat(auth): add login',
'fix: resolve crash',
'docs(readme): update',
'style: format code'
]);

const profile = await buildProfile(10);

assert.equal(profile.totalCommits, 4);
assert.equal(profile.usesScopeRate, 0.5);
} finally {
restoreEnv('HOME', originalHome);
restoreEnv('APPDATA', originalAppData);
restoreEnv('XDG_CONFIG_HOME', originalXdgConfigHome);
rmSync(tempHome, { recursive: true, force: true });
}
});

test('buildProfile computes body-usage ratio', async () => {
const originalHome = process.env.HOME;
const originalAppData = process.env.APPDATA;
const originalXdgConfigHome = process.env.XDG_CONFIG_HOME;
const tempHome = mkdtempSync(join(tmpdir(), 'commit-echo-home-'));

try {
process.env.HOME = tempHome;
process.env.APPDATA = join(tempHome, 'AppData', 'Roaming');
process.env.XDG_CONFIG_HOME = join(tempHome, '.config');
writeHistory(tempHome, [
'feat: no body',
'fix: with body\n\nThis is a body.',
'docs: no body',
'style: with body\n\nBody line 1\nBody line 2'
]);

const profile = await buildProfile(10);

assert.equal(profile.totalCommits, 4);
assert.equal(profile.usesBodyRate, 0.5);
} finally {
restoreEnv('HOME', originalHome);
restoreEnv('APPDATA', originalAppData);
restoreEnv('XDG_CONFIG_HOME', originalXdgConfigHome);
rmSync(tempHome, { recursive: true, force: true });
}
});

test('buildProfile handles empty history', async () => {
const originalHome = process.env.HOME;
const originalAppData = process.env.APPDATA;
const originalXdgConfigHome = process.env.XDG_CONFIG_HOME;
const tempHome = mkdtempSync(join(tmpdir(), 'commit-echo-home-'));

try {
process.env.HOME = tempHome;
process.env.APPDATA = join(tempHome, 'AppData', 'Roaming');
process.env.XDG_CONFIG_HOME = join(tempHome, '.config');
writeHistory(tempHome, []);

const profile = await buildProfile(10);

assert.equal(profile.totalCommits, 0);
assert.equal(profile.usesScopeRate, 0);
assert.equal(profile.usesBodyRate, 0);
assert.equal(profile.imperativeRate, 0);
assert.equal(profile.sentenceCaseRate, 0);
} finally {
restoreEnv('HOME', originalHome);
restoreEnv('APPDATA', originalAppData);
restoreEnv('XDG_CONFIG_HOME', originalXdgConfigHome);
rmSync(tempHome, { recursive: true, force: true });
}
});