|
1 | 1 | import { vi, describe, it, expect, beforeEach, afterEach, Mock } from 'vitest'; |
2 | 2 | import path from 'path'; |
3 | | -import { STATE_FILE_PATH } from '../../constants/config.js'; |
| 3 | +import { STATE_FILE_PATH, STATE_FLAGS } from '../../constants/config.js'; |
4 | 4 |
|
5 | 5 | vi.mock('../../utils/lang', () => ({ |
6 | 6 | i18n: vi.fn((key: string) => key), |
@@ -129,15 +129,15 @@ describe('config/state', () => { |
129 | 129 | expect(result).toBe(0); |
130 | 130 | }); |
131 | 131 |
|
132 | | - it('returns default value when state file has invalid structure (wrong type)', () => { |
| 132 | + it('accepts value even if type does not match default', () => { |
133 | 133 | existsSyncSpy.mockReturnValue(true); |
134 | 134 | readFileSyncSpy.mockReturnValue( |
135 | 135 | JSON.stringify({ mcpTotalToolCalls: 'not-a-number' }) |
136 | 136 | ); |
137 | 137 |
|
138 | 138 | const result = getStateValue('mcpTotalToolCalls'); |
139 | 139 |
|
140 | | - expect(result).toBe(0); |
| 140 | + expect(result).toBe('not-a-number'); |
141 | 141 | }); |
142 | 142 |
|
143 | 143 | it('ignores extra keys in state file', () => { |
@@ -174,6 +174,43 @@ describe('config/state', () => { |
174 | 174 | expect(result).toBe(0); |
175 | 175 | }); |
176 | 176 |
|
| 177 | + it('returns usageTrackingMessageLastShowVersion from state file', () => { |
| 178 | + const mockState = { |
| 179 | + mcpTotalToolCalls: 0, |
| 180 | + usageTrackingMessageLastShowVersion: '5.3.2', |
| 181 | + }; |
| 182 | + existsSyncSpy.mockReturnValue(true); |
| 183 | + readFileSyncSpy.mockReturnValue(JSON.stringify(mockState)); |
| 184 | + |
| 185 | + const result = getStateValue( |
| 186 | + STATE_FLAGS.USAGE_TRACKING_MESSAGE_LAST_SHOW_VERSION |
| 187 | + ); |
| 188 | + |
| 189 | + expect(result).toBe('5.3.2'); |
| 190 | + }); |
| 191 | + |
| 192 | + it('returns undefined for usageTrackingMessageLastShowVersion when not in state file', () => { |
| 193 | + const mockState = { mcpTotalToolCalls: 5 }; |
| 194 | + existsSyncSpy.mockReturnValue(true); |
| 195 | + readFileSyncSpy.mockReturnValue(JSON.stringify(mockState)); |
| 196 | + |
| 197 | + const result = getStateValue( |
| 198 | + STATE_FLAGS.USAGE_TRACKING_MESSAGE_LAST_SHOW_VERSION |
| 199 | + ); |
| 200 | + |
| 201 | + expect(result).toBeUndefined(); |
| 202 | + }); |
| 203 | + |
| 204 | + it('returns undefined for usageTrackingMessageLastShowVersion when file does not exist', () => { |
| 205 | + existsSyncSpy.mockReturnValue(false); |
| 206 | + |
| 207 | + const result = getStateValue( |
| 208 | + STATE_FLAGS.USAGE_TRACKING_MESSAGE_LAST_SHOW_VERSION |
| 209 | + ); |
| 210 | + |
| 211 | + expect(result).toBeUndefined(); |
| 212 | + }); |
| 213 | + |
177 | 214 | it('returns default state when JSON parses to an array', () => { |
178 | 215 | existsSyncSpy.mockReturnValue(true); |
179 | 216 | readFileSyncSpy.mockReturnValue(JSON.stringify([1, 2, 3])); |
@@ -276,18 +313,36 @@ describe('config/state', () => { |
276 | 313 | }); |
277 | 314 |
|
278 | 315 | it('preserves other state values when updating one value', () => { |
279 | | - const existingState = { mcpTotalToolCalls: 100 }; |
| 316 | + const existingState = { |
| 317 | + mcpTotalToolCalls: 100, |
| 318 | + usageTrackingMessageLastShowVersion: '5.3.0', |
| 319 | + }; |
280 | 320 | existsSyncSpy.mockReturnValue(true); |
281 | 321 | readFileSyncSpy.mockReturnValue(JSON.stringify(existingState)); |
282 | 322 | writeFileSyncSpy.mockImplementation(() => undefined); |
283 | 323 |
|
284 | 324 | setStateValue('mcpTotalToolCalls', 150); |
285 | 325 |
|
286 | | - expect(writeFileSyncSpy).toHaveBeenCalledWith( |
287 | | - STATE_FILE_PATH, |
288 | | - JSON.stringify({ mcpTotalToolCalls: 150 }, null, 2), |
289 | | - 'utf-8' |
| 326 | + const written = JSON.parse(writeFileSyncSpy.mock.calls[0][1]); |
| 327 | + expect(written.mcpTotalToolCalls).toBe(150); |
| 328 | + expect(written.usageTrackingMessageLastShowVersion).toBe('5.3.0'); |
| 329 | + }); |
| 330 | + |
| 331 | + it('sets usageTrackingMessageLastShowVersion', () => { |
| 332 | + existsSyncSpy.mockReturnValue(true); |
| 333 | + readFileSyncSpy.mockReturnValue( |
| 334 | + JSON.stringify({ mcpTotalToolCalls: 10 }) |
290 | 335 | ); |
| 336 | + writeFileSyncSpy.mockImplementation(() => undefined); |
| 337 | + |
| 338 | + setStateValue( |
| 339 | + STATE_FLAGS.USAGE_TRACKING_MESSAGE_LAST_SHOW_VERSION, |
| 340 | + '5.3.2' |
| 341 | + ); |
| 342 | + |
| 343 | + const written = JSON.parse(writeFileSyncSpy.mock.calls[0][1]); |
| 344 | + expect(written.mcpTotalToolCalls).toBe(10); |
| 345 | + expect(written.usageTrackingMessageLastShowVersion).toBe('5.3.2'); |
291 | 346 | }); |
292 | 347 |
|
293 | 348 | it('throws error when write fails with non-Error', () => { |
|
0 commit comments