From 8f8082fe3da9e1972f8b8226c68fa14e326a3d8a Mon Sep 17 00:00:00 2001
From: Arya Gummadi <aryagummadi@google.com>
Date: Mon, 18 Aug 2025 22:57:53 -0700
Subject: feat: add file change tracking to session metrics (#6094)

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Jacob Richman <jacob314@gmail.com>
---
 .../cli/src/ui/components/StatsDisplay.test.tsx    | 88 ++++++++++++++++++++++
 1 file changed, 88 insertions(+)

(limited to 'packages/cli/src/ui/components/StatsDisplay.test.tsx')

diff --git a/packages/cli/src/ui/components/StatsDisplay.test.tsx b/packages/cli/src/ui/components/StatsDisplay.test.tsx
index eed105e3..6d6fa809 100644
--- a/packages/cli/src/ui/components/StatsDisplay.test.tsx
+++ b/packages/cli/src/ui/components/StatsDisplay.test.tsx
@@ -50,6 +50,10 @@ describe('<StatsDisplay />', () => {
         totalDecisions: { accept: 0, reject: 0, modify: 0 },
         byName: {},
       },
+      files: {
+        totalLinesAdded: 0,
+        totalLinesRemoved: 0,
+      },
     };
 
     const { lastFrame } = renderWithMockedStats(zeroMetrics);
@@ -96,6 +100,10 @@ describe('<StatsDisplay />', () => {
         totalDecisions: { accept: 0, reject: 0, modify: 0 },
         byName: {},
       },
+      files: {
+        totalLinesAdded: 0,
+        totalLinesRemoved: 0,
+      },
     };
 
     const { lastFrame } = renderWithMockedStats(metrics);
@@ -139,6 +147,10 @@ describe('<StatsDisplay />', () => {
           },
         },
       },
+      files: {
+        totalLinesAdded: 0,
+        totalLinesRemoved: 0,
+      },
     };
 
     const { lastFrame } = renderWithMockedStats(metrics);
@@ -172,6 +184,10 @@ describe('<StatsDisplay />', () => {
             },
           },
         },
+        files: {
+          totalLinesAdded: 0,
+          totalLinesRemoved: 0,
+        },
       };
 
       const { lastFrame } = renderWithMockedStats(metrics);
@@ -206,6 +222,10 @@ describe('<StatsDisplay />', () => {
           totalDecisions: { accept: 0, reject: 0, modify: 0 },
           byName: {},
         },
+        files: {
+          totalLinesAdded: 0,
+          totalLinesRemoved: 0,
+        },
       };
 
       const { lastFrame } = renderWithMockedStats(metrics);
@@ -228,6 +248,10 @@ describe('<StatsDisplay />', () => {
           totalDecisions: { accept: 0, reject: 0, modify: 0 },
           byName: {},
         },
+        files: {
+          totalLinesAdded: 0,
+          totalLinesRemoved: 0,
+        },
       };
       const { lastFrame } = renderWithMockedStats(metrics);
       expect(lastFrame()).toMatchSnapshot();
@@ -244,6 +268,10 @@ describe('<StatsDisplay />', () => {
           totalDecisions: { accept: 0, reject: 0, modify: 0 },
           byName: {},
         },
+        files: {
+          totalLinesAdded: 0,
+          totalLinesRemoved: 0,
+        },
       };
       const { lastFrame } = renderWithMockedStats(metrics);
       expect(lastFrame()).toMatchSnapshot();
@@ -260,12 +288,68 @@ describe('<StatsDisplay />', () => {
           totalDecisions: { accept: 0, reject: 0, modify: 0 },
           byName: {},
         },
+        files: {
+          totalLinesAdded: 0,
+          totalLinesRemoved: 0,
+        },
       };
       const { lastFrame } = renderWithMockedStats(metrics);
       expect(lastFrame()).toMatchSnapshot();
     });
   });
 
+  describe('Code Changes Display', () => {
+    it('displays Code Changes when line counts are present', () => {
+      const metrics: SessionMetrics = {
+        models: {},
+        tools: {
+          totalCalls: 1,
+          totalSuccess: 1,
+          totalFail: 0,
+          totalDurationMs: 100,
+          totalDecisions: { accept: 0, reject: 0, modify: 0 },
+          byName: {},
+        },
+        files: {
+          totalLinesAdded: 42,
+          totalLinesRemoved: 18,
+        },
+      };
+
+      const { lastFrame } = renderWithMockedStats(metrics);
+      const output = lastFrame();
+
+      expect(output).toContain('Code Changes:');
+      expect(output).toContain('+42');
+      expect(output).toContain('-18');
+      expect(output).toMatchSnapshot();
+    });
+
+    it('hides Code Changes when no lines are added or removed', () => {
+      const metrics: SessionMetrics = {
+        models: {},
+        tools: {
+          totalCalls: 1,
+          totalSuccess: 1,
+          totalFail: 0,
+          totalDurationMs: 100,
+          totalDecisions: { accept: 0, reject: 0, modify: 0 },
+          byName: {},
+        },
+        files: {
+          totalLinesAdded: 0,
+          totalLinesRemoved: 0,
+        },
+      };
+
+      const { lastFrame } = renderWithMockedStats(metrics);
+      const output = lastFrame();
+
+      expect(output).not.toContain('Code Changes:');
+      expect(output).toMatchSnapshot();
+    });
+  });
+
   describe('Title Rendering', () => {
     const zeroMetrics: SessionMetrics = {
       models: {},
@@ -277,6 +361,10 @@ describe('<StatsDisplay />', () => {
         totalDecisions: { accept: 0, reject: 0, modify: 0 },
         byName: {},
       },
+      files: {
+        totalLinesAdded: 0,
+        totalLinesRemoved: 0,
+      },
     };
 
     it('renders the default title when no title prop is provided', () => {
-- 
cgit v1.2.3

