diff --git a/src/utils/__tests__/terminal.test.ts b/src/utils/__tests__/terminal.test.ts index 4d74ea2..53dc300 100644 --- a/src/utils/__tests__/terminal.test.ts +++ b/src/utils/__tests__/terminal.test.ts @@ -1,5 +1,6 @@ import { execSync } from 'child_process'; import { + afterEach, beforeEach, describe, expect, @@ -14,18 +15,22 @@ import { vi.mock('child_process', () => ({ execSync: vi.fn() })); -const mockExecSync = execSync as unknown as { - mock: { calls: unknown[][] }; - mockImplementationOnce: (impl: () => never) => void; - mockReturnValueOnce: (value: string) => void; -}; - describe('terminal utils', () => { + const mockExecSync = execSync as unknown as { + mock: { calls: unknown[][] }; + mockImplementationOnce: (impl: () => never) => void; + mockReturnValueOnce: (value: string) => void; + }; + beforeEach(() => { vi.clearAllMocks(); vi.restoreAllMocks(); }); + afterEach(() => { + vi.restoreAllMocks(); + }); + it('returns width from tty probe when available', () => { mockExecSync.mockReturnValueOnce('ttys001\n'); mockExecSync.mockReturnValueOnce('120\n'); diff --git a/src/utils/__tests__/usage-prefetch.test.ts b/src/utils/__tests__/usage-prefetch.test.ts index 2b63e82..0464486 100644 --- a/src/utils/__tests__/usage-prefetch.test.ts +++ b/src/utils/__tests__/usage-prefetch.test.ts @@ -1,4 +1,6 @@ import { + afterEach, + beforeEach, describe, expect, it, @@ -6,25 +8,32 @@ import { } from 'vitest'; import type { WidgetItem } from '../../types/Widget'; -import { fetchUsageData } from '../usage'; +import * as usage from '../usage'; import { hasUsageDependentWidgets, prefetchUsageDataIfNeeded } from '../usage-prefetch'; - -vi.mock('../usage', () => ({ fetchUsageData: vi.fn() })); - -const mockFetchUsageData = fetchUsageData as unknown as { - mockClear: () => void; - mockResolvedValue: (value: unknown) => void; - mock: { calls: unknown[][] }; -}; +import type { UsageData } from '../usage-types'; function makeLines(...lineItems: WidgetItem[][]): WidgetItem[][] { return lineItems; } describe('usage prefetch', () => { + let mockFetchUsageData: { + mock: { calls: unknown[][] }; + mockResolvedValue: (value: UsageData) => void; + }; + + beforeEach(() => { + vi.restoreAllMocks(); + mockFetchUsageData = vi.spyOn(usage, 'fetchUsageData'); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + it.each([ { expected: true, @@ -47,7 +56,6 @@ describe('usage prefetch', () => { }); it('fetches usage data once when at least one usage widget exists', async () => { - mockFetchUsageData.mockClear(); mockFetchUsageData.mockResolvedValue({ sessionUsage: 12.3 }); const lines = makeLines( @@ -62,8 +70,6 @@ describe('usage prefetch', () => { }); it('does not fetch usage data when no usage widgets exist', async () => { - mockFetchUsageData.mockClear(); - const lines = makeLines( [{ id: '1', type: 'model' }], [{ id: '2', type: 'git-branch' }] diff --git a/src/utils/__tests__/usage.test.ts b/src/utils/__tests__/usage.test.ts index feab42a..7bc03b1 100644 --- a/src/utils/__tests__/usage.test.ts +++ b/src/utils/__tests__/usage.test.ts @@ -1,4 +1,5 @@ import { + afterEach, beforeEach, describe, expect, @@ -7,27 +8,32 @@ import { } from 'vitest'; import type { BlockMetrics } from '../../types'; -import { getCachedBlockMetrics } from '../jsonl'; +import * as jsonl from '../jsonl'; import { FIVE_HOUR_BLOCK_MS, - SEVEN_DAY_WINDOW_MS, + SEVEN_DAY_WINDOW_MS +} from '../usage-types'; +import { formatUsageDuration, getUsageWindowFromResetAt, getWeeklyUsageWindowFromResetAt, resolveUsageWindowWithFallback, resolveWeeklyUsageWindow -} from '../usage'; - -vi.mock('../jsonl', () => ({ getCachedBlockMetrics: vi.fn() })); - -const mockGetCachedBlockMetrics = getCachedBlockMetrics as unknown as { - mock: { calls: unknown[][] }; - mockReturnValue: (value: BlockMetrics | null) => void; -}; +} from '../usage-windows'; describe('usage window helpers', () => { + let mockGetCachedBlockMetrics: { + mock: { calls: unknown[][] }; + mockReturnValue: (value: BlockMetrics | null) => void; + }; + beforeEach(() => { - vi.clearAllMocks(); + vi.restoreAllMocks(); + mockGetCachedBlockMetrics = vi.spyOn(jsonl, 'getCachedBlockMetrics'); + }); + + afterEach(() => { + vi.restoreAllMocks(); }); it('parses usage reset timestamp into elapsed and remaining metrics', () => { diff --git a/src/widgets/__tests__/BlockResetTimer.test.ts b/src/widgets/__tests__/BlockResetTimer.test.ts index 15818ad..8b4bad1 100644 --- a/src/widgets/__tests__/BlockResetTimer.test.ts +++ b/src/widgets/__tests__/BlockResetTimer.test.ts @@ -1,4 +1,5 @@ import { + afterEach, beforeEach, describe, expect, @@ -9,32 +10,30 @@ import { import type { RenderContext } from '../../types/RenderContext'; import { DEFAULT_SETTINGS } from '../../types/Settings'; import type { WidgetItem } from '../../types/Widget'; -import { - formatUsageDuration, - getUsageErrorMessage, - resolveUsageWindowWithFallback -} from '../../utils/usage'; +import * as usage from '../../utils/usage'; +import type { UsageWindowMetrics } from '../../utils/usage-types'; import { BlockResetTimerWidget } from '../BlockResetTimer'; import { runUsageTimerEditorSuite } from './helpers/usage-widget-suites'; -vi.mock('../../utils/usage', () => ({ - formatUsageDuration: vi.fn(), - getUsageErrorMessage: vi.fn(), - resolveUsageWindowWithFallback: vi.fn() -})); - -const mockFormatUsageDuration = formatUsageDuration as unknown as { mockReturnValue: (value: string) => void }; -const mockGetUsageErrorMessage = getUsageErrorMessage as unknown as { mockReturnValue: (value: string) => void }; -const mockResolveUsageWindowWithFallback = resolveUsageWindowWithFallback as unknown as { mockReturnValue: (value: unknown) => void }; - function render(widget: BlockResetTimerWidget, item: WidgetItem, context: RenderContext = {}): string | null { return widget.render(item, context, DEFAULT_SETTINGS); } describe('BlockResetTimerWidget', () => { + let mockFormatUsageDuration: { mockReturnValue: (value: string) => void }; + let mockGetUsageErrorMessage: { mockReturnValue: (value: string) => void }; + let mockResolveUsageWindowWithFallback: { mockReturnValue: (value: UsageWindowMetrics | null) => void }; + beforeEach(() => { - vi.clearAllMocks(); + vi.restoreAllMocks(); + mockFormatUsageDuration = vi.spyOn(usage, 'formatUsageDuration'); + mockGetUsageErrorMessage = vi.spyOn(usage, 'getUsageErrorMessage'); + mockResolveUsageWindowWithFallback = vi.spyOn(usage, 'resolveUsageWindowWithFallback'); + }); + + afterEach(() => { + vi.restoreAllMocks(); }); it('renders preview using block-style reset format', () => { diff --git a/src/widgets/__tests__/BlockTimer.test.ts b/src/widgets/__tests__/BlockTimer.test.ts index f2cb28b..d3004c1 100644 --- a/src/widgets/__tests__/BlockTimer.test.ts +++ b/src/widgets/__tests__/BlockTimer.test.ts @@ -1,4 +1,5 @@ import { + afterEach, beforeEach, describe, expect, @@ -9,29 +10,28 @@ import { import type { RenderContext } from '../../types/RenderContext'; import { DEFAULT_SETTINGS } from '../../types/Settings'; import type { WidgetItem } from '../../types/Widget'; -import { - formatUsageDuration, - resolveUsageWindowWithFallback -} from '../../utils/usage'; +import * as usage from '../../utils/usage'; +import type { UsageWindowMetrics } from '../../utils/usage-types'; import { BlockTimerWidget } from '../BlockTimer'; import { runUsageTimerEditorSuite } from './helpers/usage-widget-suites'; -vi.mock('../../utils/usage', () => ({ - formatUsageDuration: vi.fn(), - resolveUsageWindowWithFallback: vi.fn() -})); - -const mockFormatUsageDuration = formatUsageDuration as unknown as { mockReturnValue: (value: string) => void }; -const mockResolveUsageWindowWithFallback = resolveUsageWindowWithFallback as unknown as { mockReturnValue: (value: unknown) => void }; - function render(widget: BlockTimerWidget, item: WidgetItem, context: RenderContext = {}): string | null { return widget.render(item, context, DEFAULT_SETTINGS); } describe('BlockTimerWidget', () => { + let mockFormatUsageDuration: { mockReturnValue: (value: string) => void }; + let mockResolveUsageWindowWithFallback: { mockReturnValue: (value: UsageWindowMetrics | null) => void }; + beforeEach(() => { - vi.clearAllMocks(); + vi.restoreAllMocks(); + mockFormatUsageDuration = vi.spyOn(usage, 'formatUsageDuration'); + mockResolveUsageWindowWithFallback = vi.spyOn(usage, 'resolveUsageWindowWithFallback'); + }); + + afterEach(() => { + vi.restoreAllMocks(); }); it('renders elapsed time in time mode', () => { diff --git a/src/widgets/__tests__/ContextBar.test.ts b/src/widgets/__tests__/ContextBar.test.ts index 342c2eb..7f277f0 100644 --- a/src/widgets/__tests__/ContextBar.test.ts +++ b/src/widgets/__tests__/ContextBar.test.ts @@ -1,4 +1,6 @@ import { + afterEach, + beforeEach, describe, expect, it, @@ -7,11 +9,19 @@ import { import type { RenderContext } from '../../types'; import { DEFAULT_SETTINGS } from '../../types/Settings'; +import * as usage from '../../utils/usage'; import { ContextBarWidget } from '../ContextBar'; -vi.mock('../../utils/usage', () => ({ makeUsageProgressBar: vi.fn((percent: number, width = 15) => `[bar:${percent.toFixed(1)}:${width}]`) })); - describe('ContextBarWidget', () => { + beforeEach(() => { + vi.restoreAllMocks(); + vi.spyOn(usage, 'makeUsageProgressBar').mockImplementation((percent: number, width = 15) => `[bar:${percent.toFixed(1)}:${width}]`); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + it('renders from context_window data when available', () => { const context: RenderContext = { data: { diff --git a/src/widgets/__tests__/CurrentWorkingDir.test.ts b/src/widgets/__tests__/CurrentWorkingDir.test.ts index d3b1711..ae96ec4 100644 --- a/src/widgets/__tests__/CurrentWorkingDir.test.ts +++ b/src/widgets/__tests__/CurrentWorkingDir.test.ts @@ -13,24 +13,18 @@ import type { Settings } from '../../types/Settings'; import type { WidgetItem } from '../../types/Widget'; import { CurrentWorkingDirWidget } from '../CurrentWorkingDir'; -vi.mock('node:os', () => ({ homedir: vi.fn() })); - -const mockHomedir = os.homedir as unknown as { - mockReset: () => void; - mockReturnValue: (value: string) => void; -}; - describe('CurrentWorkingDirWidget', () => { const widget = new CurrentWorkingDirWidget(); const defaultHomeDir = '/Users/alice'; + let mockHomedir: { mockReturnValue: (value: string) => void }; beforeEach(() => { - mockHomedir.mockReset(); - mockHomedir.mockReturnValue(defaultHomeDir); + vi.restoreAllMocks(); + mockHomedir = vi.spyOn(os, 'homedir').mockReturnValue(defaultHomeDir); }); afterEach(() => { - vi.clearAllMocks(); + vi.restoreAllMocks(); }); const createContext = (cwd?: string, isPreview = false): RenderContext => ({ diff --git a/src/widgets/__tests__/FreeMemory.test.ts b/src/widgets/__tests__/FreeMemory.test.ts index 12a1588..98af78d 100644 --- a/src/widgets/__tests__/FreeMemory.test.ts +++ b/src/widgets/__tests__/FreeMemory.test.ts @@ -1,4 +1,4 @@ -import { execSync } from 'child_process'; +import * as childProcess from 'child_process'; import os from 'os'; import { afterEach, @@ -16,47 +16,22 @@ import type { import { DEFAULT_SETTINGS } from '../../types/Settings'; import { FreeMemoryWidget } from '../FreeMemory'; -vi.mock('child_process', () => ({ execSync: vi.fn() })); -vi.mock('os', () => { - const mockOs = { - totalmem: vi.fn(), - freemem: vi.fn(), - platform: vi.fn() - }; - - return { - default: mockOs, - ...mockOs - }; -}); - -const mockTotalmem = os.totalmem as unknown as { - mockReturnValue: (value: number) => void; - mockReset: () => void; -}; -const mockFreemem = os.freemem as unknown as { - mockReturnValue: (value: number) => void; - mockReset: () => void; -}; -const mockPlatform = os.platform as unknown as { - mockReturnValue: (value: NodeJS.Platform) => void; - mockReset: () => void; -}; -const mockExecSync = execSync as unknown as { - mockReturnValue: (value: string) => void; - mockImplementation: (impl: () => never) => void; - mockReset: () => void; -}; - describe('FreeMemoryWidget', () => { const widget = new FreeMemoryWidget(); + let mockTotalmem: { mockReturnValue: (value: number) => void }; + let mockFreemem: { mockReturnValue: (value: number) => void }; + let mockPlatform: { mockReturnValue: (value: NodeJS.Platform) => void }; + let mockExecSync: { + mockImplementation: (fn: () => never) => void; + mockReturnValue: (value: string) => void; + }; beforeEach(() => { - vi.clearAllMocks(); - mockTotalmem.mockReset(); - mockFreemem.mockReset(); - mockPlatform.mockReset(); - mockExecSync.mockReset(); + vi.restoreAllMocks(); + mockTotalmem = vi.spyOn(os, 'totalmem'); + mockFreemem = vi.spyOn(os, 'freemem'); + mockPlatform = vi.spyOn(os, 'platform'); + mockExecSync = vi.spyOn(childProcess, 'execSync'); }); afterEach(() => { diff --git a/src/widgets/__tests__/SessionName.test.ts b/src/widgets/__tests__/SessionName.test.ts index b26e3a2..7b1672d 100644 --- a/src/widgets/__tests__/SessionName.test.ts +++ b/src/widgets/__tests__/SessionName.test.ts @@ -1,4 +1,4 @@ -import { readFileSync } from 'fs'; +import * as fs from 'fs'; import { afterEach, beforeEach, @@ -15,12 +15,7 @@ import type { import { DEFAULT_SETTINGS } from '../../types/Settings'; import { SessionNameWidget } from '../SessionName'; -vi.mock('fs', () => ({ readFileSync: vi.fn() })); - -const mockReadFileSync = readFileSync as unknown as { - mockImplementation: (impl: () => string) => void; - mockReset: () => void; -}; +let mockReadFileSync: { mockImplementation: (fn: () => string | never) => void }; function render(transcriptPath: string | undefined, fileContent: string | null, rawValue = false, isPreview = false) { const widget = new SessionNameWidget(); @@ -47,8 +42,8 @@ function render(transcriptPath: string | undefined, fileContent: string | null, describe('SessionNameWidget', () => { beforeEach(() => { - vi.clearAllMocks(); - mockReadFileSync.mockReset(); + vi.restoreAllMocks(); + mockReadFileSync = vi.spyOn(fs, 'readFileSync'); }); afterEach(() => { diff --git a/src/widgets/__tests__/SessionUsage.test.ts b/src/widgets/__tests__/SessionUsage.test.ts index 7139de2..777dea7 100644 --- a/src/widgets/__tests__/SessionUsage.test.ts +++ b/src/widgets/__tests__/SessionUsage.test.ts @@ -1,4 +1,6 @@ import { + afterEach, + beforeEach, describe, vi } from 'vitest'; @@ -6,27 +8,37 @@ import { import type { RenderContext } from '../../types/RenderContext'; import { DEFAULT_SETTINGS } from '../../types/Settings'; import type { WidgetItem } from '../../types/Widget'; -import { getUsageErrorMessage } from '../../utils/usage'; +import * as usage from '../../utils/usage'; import { SessionUsageWidget } from '../SessionUsage'; import { runUsagePercentWidgetSuite } from './helpers/usage-widget-suites'; -vi.mock('../../utils/usage', () => ({ - getUsageErrorMessage: vi.fn(), - makeUsageProgressBar: vi.fn((percent: number, width = 15) => `[bar:${percent.toFixed(1)}:${width}]`) -})); - -const mockGetUsageErrorMessage = getUsageErrorMessage as unknown as { mockReturnValue: (value: string) => void }; +let mockGetUsageErrorMessage: { mockReturnValue: (value: string) => void }; +const usageErrorMessageMock = { + mockReturnValue(value: string): void { + mockGetUsageErrorMessage.mockReturnValue(value); + } +}; function render(widget: SessionUsageWidget, item: WidgetItem, context: RenderContext = {}): string | null { return widget.render(item, context, DEFAULT_SETTINGS); } describe('SessionUsageWidget', () => { + beforeEach(() => { + vi.restoreAllMocks(); + mockGetUsageErrorMessage = vi.spyOn(usage, 'getUsageErrorMessage'); + vi.spyOn(usage, 'makeUsageProgressBar').mockImplementation((percent: number, width = 15) => `[bar:${percent.toFixed(1)}:${width}]`); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + runUsagePercentWidgetSuite({ baseItem: { id: 'session', type: 'session-usage' }, createWidget: () => new SessionUsageWidget(), - errorMessageMock: mockGetUsageErrorMessage, + errorMessageMock: usageErrorMessageMock, expectedModifierText: '(short bar, inverted)', expectedProgress: 'Session: [bar:76.5:16] 76.5%', expectedRawProgress: '[bar:23.4:32] 23.4%', diff --git a/src/widgets/__tests__/TokensWidgets.test.ts b/src/widgets/__tests__/TokensWidgets.test.ts index d5ac241..29b9fb5 100644 --- a/src/widgets/__tests__/TokensWidgets.test.ts +++ b/src/widgets/__tests__/TokensWidgets.test.ts @@ -1,4 +1,6 @@ import { + afterEach, + beforeEach, describe, expect, it, @@ -7,8 +9,7 @@ import { import type { RenderContext } from '../../types'; import { DEFAULT_SETTINGS } from '../../types/Settings'; - -vi.mock('../../utils/renderer', () => ({ formatTokens: vi.fn((value: number) => `fmt:${value}`) })); +import * as renderer from '../../utils/renderer'; async function loadWidgets() { const [{ TokensInputWidget }, { TokensOutputWidget }, { TokensCachedWidget }, { TokensTotalWidget }] = await Promise.all([ @@ -27,6 +28,15 @@ async function loadWidgets() { } describe('Token widgets', () => { + beforeEach(() => { + vi.restoreAllMocks(); + vi.spyOn(renderer, 'formatTokens').mockImplementation((value: number) => `fmt:${value}`); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + it('use context_window values for input/output and tokenMetrics totals for cached/total', async () => { const { TokensCachedWidget, TokensInputWidget, TokensOutputWidget, TokensTotalWidget } = await loadWidgets(); const context: RenderContext = { diff --git a/src/widgets/__tests__/WeeklyResetTimer.test.ts b/src/widgets/__tests__/WeeklyResetTimer.test.ts index a83d80d..341095b 100644 --- a/src/widgets/__tests__/WeeklyResetTimer.test.ts +++ b/src/widgets/__tests__/WeeklyResetTimer.test.ts @@ -1,4 +1,5 @@ import { + afterEach, beforeEach, describe, expect, @@ -9,32 +10,30 @@ import { import type { RenderContext } from '../../types/RenderContext'; import { DEFAULT_SETTINGS } from '../../types/Settings'; import type { WidgetItem } from '../../types/Widget'; -import { - formatUsageDuration, - getUsageErrorMessage, - resolveWeeklyUsageWindow -} from '../../utils/usage'; +import * as usage from '../../utils/usage'; +import type { UsageWindowMetrics } from '../../utils/usage-types'; import { WeeklyResetTimerWidget } from '../WeeklyResetTimer'; import { runUsageTimerEditorSuite } from './helpers/usage-widget-suites'; -vi.mock('../../utils/usage', () => ({ - formatUsageDuration: vi.fn(), - getUsageErrorMessage: vi.fn(), - resolveWeeklyUsageWindow: vi.fn() -})); - -const mockFormatUsageDuration = formatUsageDuration as unknown as { mockReturnValue: (value: string) => void }; -const mockGetUsageErrorMessage = getUsageErrorMessage as unknown as { mockReturnValue: (value: string) => void }; -const mockResolveWeeklyUsageWindow = resolveWeeklyUsageWindow as unknown as { mockReturnValue: (value: unknown) => void }; - function render(widget: WeeklyResetTimerWidget, item: WidgetItem, context: RenderContext = {}): string | null { return widget.render(item, context, DEFAULT_SETTINGS); } describe('WeeklyResetTimerWidget', () => { + let mockFormatUsageDuration: { mockReturnValue: (value: string) => void }; + let mockGetUsageErrorMessage: { mockReturnValue: (value: string) => void }; + let mockResolveWeeklyUsageWindow: { mockReturnValue: (value: UsageWindowMetrics | null) => void }; + beforeEach(() => { - vi.clearAllMocks(); + vi.restoreAllMocks(); + mockFormatUsageDuration = vi.spyOn(usage, 'formatUsageDuration'); + mockGetUsageErrorMessage = vi.spyOn(usage, 'getUsageErrorMessage'); + mockResolveWeeklyUsageWindow = vi.spyOn(usage, 'resolveWeeklyUsageWindow'); + }); + + afterEach(() => { + vi.restoreAllMocks(); }); it('renders preview using weekly reset format', () => { diff --git a/src/widgets/__tests__/WeeklyUsage.test.ts b/src/widgets/__tests__/WeeklyUsage.test.ts index 5b42e12..fa97a94 100644 --- a/src/widgets/__tests__/WeeklyUsage.test.ts +++ b/src/widgets/__tests__/WeeklyUsage.test.ts @@ -1,4 +1,6 @@ import { + afterEach, + beforeEach, describe, vi } from 'vitest'; @@ -6,27 +8,37 @@ import { import type { RenderContext } from '../../types/RenderContext'; import { DEFAULT_SETTINGS } from '../../types/Settings'; import type { WidgetItem } from '../../types/Widget'; -import { getUsageErrorMessage } from '../../utils/usage'; +import * as usage from '../../utils/usage'; import { WeeklyUsageWidget } from '../WeeklyUsage'; import { runUsagePercentWidgetSuite } from './helpers/usage-widget-suites'; -vi.mock('../../utils/usage', () => ({ - getUsageErrorMessage: vi.fn(), - makeUsageProgressBar: vi.fn((percent: number, width = 15) => `[bar:${percent.toFixed(1)}:${width}]`) -})); - -const mockGetUsageErrorMessage = getUsageErrorMessage as unknown as { mockReturnValue: (value: string) => void }; +let mockGetUsageErrorMessage: { mockReturnValue: (value: string) => void }; +const usageErrorMessageMock = { + mockReturnValue(value: string): void { + mockGetUsageErrorMessage.mockReturnValue(value); + } +}; function render(widget: WeeklyUsageWidget, item: WidgetItem, context: RenderContext = {}): string | null { return widget.render(item, context, DEFAULT_SETTINGS); } describe('WeeklyUsageWidget', () => { + beforeEach(() => { + vi.restoreAllMocks(); + mockGetUsageErrorMessage = vi.spyOn(usage, 'getUsageErrorMessage'); + vi.spyOn(usage, 'makeUsageProgressBar').mockImplementation((percent: number, width = 15) => `[bar:${percent.toFixed(1)}:${width}]`); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + runUsagePercentWidgetSuite({ baseItem: { id: 'weekly', type: 'weekly-usage' }, createWidget: () => new WeeklyUsageWidget(), - errorMessageMock: mockGetUsageErrorMessage, + errorMessageMock: usageErrorMessageMock, expectedModifierText: '(progress bar, inverted)', expectedProgress: 'Weekly: [bar:57.9:32] 57.9%', expectedRawProgress: '[bar:42.1:16] 42.1%',