diff --git a/packages/cli/src/config/footerItems.test.ts b/packages/cli/src/config/footerItems.test.ts index 420246811b..d9ef9bc3f2 100644 --- a/packages/cli/src/config/footerItems.test.ts +++ b/packages/cli/src/config/footerItems.test.ts @@ -5,87 +5,153 @@ */ import { describe, it, expect } from 'vitest'; -import { deriveItemsFromLegacySettings } from './footerItems.js'; +import { + deriveItemsFromLegacySettings, + resolveFooterState, +} from './footerItems.js'; import { createMockSettings } from '../test-utils/settings.js'; -describe('deriveItemsFromLegacySettings', () => { - it('returns defaults when no legacy settings are customized', () => { - const settings = createMockSettings({ - ui: { footer: { hideContextPercentage: true } }, - }).merged; - const items = deriveItemsFromLegacySettings(settings); - expect(items).toEqual([ - 'workspace', - 'git-branch', - 'sandbox', - 'model-name', - 'quota', - ]); - }); +describe('footerItems', () => { + describe('deriveItemsFromLegacySettings', () => { + it('returns defaults when no legacy settings are customized', () => { + const settings = createMockSettings({ + ui: { footer: { hideContextPercentage: true } }, + }).merged; + const items = deriveItemsFromLegacySettings(settings); + expect(items).toEqual([ + 'workspace', + 'git-branch', + 'sandbox', + 'model-name', + 'quota', + ]); + }); - it('removes workspace when hideCWD is true', () => { - const settings = createMockSettings({ - ui: { footer: { hideCWD: true, hideContextPercentage: true } }, - }).merged; - const items = deriveItemsFromLegacySettings(settings); - expect(items).not.toContain('workspace'); - }); + it('removes workspace when hideCWD is true', () => { + const settings = createMockSettings({ + ui: { footer: { hideCWD: true, hideContextPercentage: true } }, + }).merged; + const items = deriveItemsFromLegacySettings(settings); + expect(items).not.toContain('workspace'); + }); - it('removes sandbox when hideSandboxStatus is true', () => { - const settings = createMockSettings({ - ui: { footer: { hideSandboxStatus: true, hideContextPercentage: true } }, - }).merged; - const items = deriveItemsFromLegacySettings(settings); - expect(items).not.toContain('sandbox'); - }); - - it('removes model-name, context-used, and quota when hideModelInfo is true', () => { - const settings = createMockSettings({ - ui: { footer: { hideModelInfo: true, hideContextPercentage: true } }, - }).merged; - const items = deriveItemsFromLegacySettings(settings); - expect(items).not.toContain('model-name'); - expect(items).not.toContain('context-used'); - expect(items).not.toContain('quota'); - }); - - it('includes context-used when hideContextPercentage is false', () => { - const settings = createMockSettings({ - ui: { footer: { hideContextPercentage: false } }, - }).merged; - const items = deriveItemsFromLegacySettings(settings); - expect(items).toContain('context-used'); - // Should be after model-name - const modelIdx = items.indexOf('model-name'); - const contextIdx = items.indexOf('context-used'); - expect(contextIdx).toBe(modelIdx + 1); - }); - - it('includes memory-usage when showMemoryUsage is true', () => { - const settings = createMockSettings({ - ui: { showMemoryUsage: true, footer: { hideContextPercentage: true } }, - }).merged; - const items = deriveItemsFromLegacySettings(settings); - expect(items).toContain('memory-usage'); - }); - - it('handles combination of settings', () => { - const settings = createMockSettings({ - ui: { - showMemoryUsage: true, - footer: { - hideCWD: true, - hideModelInfo: true, - hideContextPercentage: false, + it('removes sandbox when hideSandboxStatus is true', () => { + const settings = createMockSettings({ + ui: { + footer: { hideSandboxStatus: true, hideContextPercentage: true }, }, - }, - }).merged; - const items = deriveItemsFromLegacySettings(settings); - expect(items).toEqual([ - 'git-branch', - 'sandbox', - 'context-used', - 'memory-usage', - ]); + }).merged; + const items = deriveItemsFromLegacySettings(settings); + expect(items).not.toContain('sandbox'); + }); + + it('removes model-name, context-used, and quota when hideModelInfo is true', () => { + const settings = createMockSettings({ + ui: { footer: { hideModelInfo: true, hideContextPercentage: true } }, + }).merged; + const items = deriveItemsFromLegacySettings(settings); + expect(items).not.toContain('model-name'); + expect(items).not.toContain('context-used'); + expect(items).not.toContain('quota'); + }); + + it('includes context-used when hideContextPercentage is false', () => { + const settings = createMockSettings({ + ui: { footer: { hideContextPercentage: false } }, + }).merged; + const items = deriveItemsFromLegacySettings(settings); + expect(items).toContain('context-used'); + // Should be after model-name + const modelIdx = items.indexOf('model-name'); + const contextIdx = items.indexOf('context-used'); + expect(contextIdx).toBe(modelIdx + 1); + }); + + it('includes memory-usage when showMemoryUsage is true', () => { + const settings = createMockSettings({ + ui: { showMemoryUsage: true, footer: { hideContextPercentage: true } }, + }).merged; + const items = deriveItemsFromLegacySettings(settings); + expect(items).toContain('memory-usage'); + }); + + it('handles combination of settings', () => { + const settings = createMockSettings({ + ui: { + showMemoryUsage: true, + footer: { + hideCWD: true, + hideModelInfo: true, + hideContextPercentage: false, + }, + }, + }).merged; + const items = deriveItemsFromLegacySettings(settings); + expect(items).toEqual([ + 'git-branch', + 'sandbox', + 'context-used', + 'memory-usage', + ]); + }); + }); + + describe('resolveFooterState', () => { + it('filters out auth item when showUserIdentity is false', () => { + const settings = createMockSettings({ + ui: { + showUserIdentity: false, + footer: { + items: ['workspace', 'auth', 'model-name'], + }, + }, + }).merged; + + const state = resolveFooterState(settings); + expect(state.orderedIds).not.toContain('auth'); + expect(state.selectedIds.has('auth')).toBe(false); + // It should also not be in the 'others' part of orderedIds + expect(state.orderedIds).toEqual([ + 'workspace', + 'model-name', + 'git-branch', + 'sandbox', + 'context-used', + 'quota', + 'memory-usage', + 'session-id', + 'code-changes', + 'token-count', + ]); + }); + + it('includes auth item when showUserIdentity is true', () => { + const settings = createMockSettings({ + ui: { + showUserIdentity: true, + footer: { + items: ['workspace', 'auth', 'model-name'], + }, + }, + }).merged; + + const state = resolveFooterState(settings); + expect(state.orderedIds).toContain('auth'); + expect(state.selectedIds.has('auth')).toBe(true); + }); + + it('includes auth item by default when showUserIdentity is undefined (defaults to true)', () => { + const settings = createMockSettings({ + ui: { + footer: { + items: ['workspace', 'auth', 'model-name'], + }, + }, + }).merged; + + const state = resolveFooterState(settings); + expect(state.orderedIds).toContain('auth'); + expect(state.selectedIds.has('auth')).toBe(true); + }); }); }); diff --git a/packages/cli/src/config/footerItems.ts b/packages/cli/src/config/footerItems.ts index 8410d0b5ec..9f3943b692 100644 --- a/packages/cli/src/config/footerItems.ts +++ b/packages/cli/src/config/footerItems.ts @@ -47,6 +47,11 @@ export const ALL_ITEMS = [ header: 'session', description: 'Unique identifier for the current session', }, + { + id: 'auth', + header: '/auth', + description: 'Current authentication info', + }, { id: 'code-changes', header: 'diff', @@ -70,6 +75,7 @@ export const DEFAULT_ORDER = [ 'quota', 'memory-usage', 'session-id', + 'auth', 'code-changes', 'token-count', ]; @@ -121,10 +127,19 @@ export function resolveFooterState(settings: MergedSettings): { orderedIds: string[]; selectedIds: Set; } { + const showUserIdentity = settings.ui?.showUserIdentity !== false; + const filteredValidIds = showUserIdentity + ? VALID_IDS + : new Set([...VALID_IDS].filter((id) => id !== 'auth')); + const source = ( settings.ui?.footer?.items ?? deriveItemsFromLegacySettings(settings) - ).filter((id: string) => VALID_IDS.has(id)); - const others = DEFAULT_ORDER.filter((id) => !source.includes(id)); + ).filter((id: string) => filteredValidIds.has(id)); + + const others = DEFAULT_ORDER.filter( + (id) => !source.includes(id) && filteredValidIds.has(id), + ); + return { orderedIds: [...source, ...others], selectedIds: new Set(source), diff --git a/packages/cli/src/ui/components/Footer.test.tsx b/packages/cli/src/ui/components/Footer.test.tsx index c0a52af868..1ed20a42b5 100644 --- a/packages/cli/src/ui/components/Footer.test.tsx +++ b/packages/cli/src/ui/components/Footer.test.tsx @@ -8,7 +8,11 @@ import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest'; import { renderWithProviders } from '../../test-utils/render.js'; import { Footer } from './Footer.js'; import { createMockSettings } from '../../test-utils/settings.js'; -import { type Config } from '@google/gemini-cli-core'; +import { + type Config, + UserAccountManager, + AuthType, +} from '@google/gemini-cli-core'; import path from 'node:path'; // Normalize paths to POSIX slashes for stable cross-platform snapshots. @@ -69,14 +73,17 @@ const defaultProps = { branchName: 'main', }; -const mockConfig = { +const mockConfigPlain = { getTargetDir: () => defaultProps.targetDir, getDebugMode: () => false, getModel: () => defaultProps.model, getIdeMode: () => false, isTrustedFolder: () => true, getExtensionRegistryURI: () => undefined, -} as unknown as Config; + getContentGeneratorConfig: () => ({ authType: undefined }), +}; + +const mockConfig = mockConfigPlain as unknown as Config; const mockSessionStats = { sessionId: 'test-session-id', @@ -675,6 +682,75 @@ describe('