// SPDX-FileCopyrightText: 2026 FocusFlow contributors // SPDX-License-Identifier: AGPL-3.0-only /// Tests FocusFlow runtime config and file logging behavior. library; import 'dart:convert'; import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; import 'package:focus_flow_flutter/app/runtime/focus_flow_file_logger.dart'; import 'package:focus_flow_flutter/app/runtime/focus_flow_runtime_config.dart'; /// Runs runtime config tests. void main() { group('FocusFlowRuntimeConfig', () { test('missing config file leaves optional settings unset', () async { final directory = await Directory.systemTemp.createTemp( 'focus-flow-config-test-', ); addTearDown(() => directory.delete(recursive: true)); final config = await FocusFlowRuntimeConfig.load( path: '${directory.path}${Platform.pathSeparator}missing.json', ); expect(config.logLevel, isNull); expect(config.logFileLocation, isNull); expect(config.enablesFileLogging, isFalse); }); test('loads supported settings from a config file', () async { final directory = await Directory.systemTemp.createTemp( 'focus-flow-config-file-test-', ); addTearDown(() => directory.delete(recursive: true)); final configFile = File( '${directory.path}${Platform.pathSeparator}config.json', ); await configFile.writeAsString( jsonEncode({'LogLevel': 'trace', 'LogfileLocation': directory.path}), ); final config = await FocusFlowRuntimeConfig.load(path: configFile.path); expect(config.logLevel, FocusFlowLogLevel.trace); expect(config.logFileLocation, directory.path); expect(config.enablesFileLogging, isTrue); }); test('loads supported logging settings from JSON', () { final config = FocusFlowRuntimeConfig.fromJson({ 'LogLevel': 'debug', 'LogfileLocation': '/tmp/focus-flow-logs', }); expect(config.logLevel, FocusFlowLogLevel.debug); expect(config.logFileLocation, '/tmp/focus-flow-logs'); expect(config.enablesFileLogging, isTrue); }); test('ignores missing and unsupported optional settings', () { final config = FocusFlowRuntimeConfig.fromJson({ 'LogLevel': 'verbose', 'LogfileLocation': ' ', }); expect(config.logLevel, isNull); expect(config.logFileLocation, isNull); expect(config.enablesFileLogging, isFalse); }); }); group('FocusFlowFileLogger', () { test('does nothing unless both logging settings are set', () async { final logger = await FocusFlowFileLogger.open( const FocusFlowRuntimeConfig(logLevel: FocusFlowLogLevel.debug), ); expect(logger.isEnabled, isFalse); await logger.info('ignored'); }); test('writes messages at or above the configured level', () async { final directory = await Directory.systemTemp.createTemp( 'focus-flow-log-test-', ); addTearDown(() => directory.delete(recursive: true)); final logger = await FocusFlowFileLogger.open( FocusFlowRuntimeConfig( logLevel: FocusFlowLogLevel.warn, logFileLocation: directory.path, ), now: () => DateTime.utc(2026, 7, 3, 12), ); await logger.info('not written'); await logger.warn('written warning'); await logger.error('written error', error: 'boom'); final logFile = File( '${directory.path}${Platform.pathSeparator}focus_flow.log', ); final contents = await logFile.readAsString(); expect(contents, isNot(contains('not written'))); expect(contents, contains('2026-07-03T12:00:00.000Z WARN')); expect(contents, contains('written warning')); expect(contents, contains('ERROR written error | error=boom')); }); }); }