diff --git a/finlog_app/fluttery/lib/preferences/preferences.dart b/finlog_app/fluttery/lib/preferences/preferences.dart new file mode 100644 index 0000000..f0b7585 --- /dev/null +++ b/finlog_app/fluttery/lib/preferences/preferences.dart @@ -0,0 +1,40 @@ +import 'package:fluttery/fluttery.dart'; + +/// providing methods for managing persistent storage of key-value pairs. +abstract class Preferences implements Service { + /// Stores a string value with the given [key]. + Future setString(String key, String value); + + /// Retrieves the string value associated with the given [key]. + Future getString(String key); + + /// Stores an integer value with the given [key]. + Future setInt(String key, int value); + + /// Retrieves the integer value associated with the given [key]. + Future getInt(String key); + + /// Stores a boolean value with the given [key]. + Future setBool(String key, bool value); + + /// Retrieves the boolean value associated with the given [key]. + Future getBool(String key); + + /// Stores a double value with the given [key]. + Future setDouble(String key, double value); + + /// Retrieves the double value associated with the given [key]. + Future getDouble(String key); + + /// Stores a list of strings with the given [key]. + Future setStringList(String key, List value); + + /// Retrieves the list of strings associated with the given [key]. + Future?> getStringList(String key); + + /// Removes the key-value pair associated with the given [key]. + Future remove(String key); + + /// Clears all key-value pairs in the preferences. + Future clear(); +} diff --git a/finlog_app/fluttery/lib/src/preferences/preferences_impl.dart b/finlog_app/fluttery/lib/src/preferences/preferences_impl.dart new file mode 100644 index 0000000..9b21f10 --- /dev/null +++ b/finlog_app/fluttery/lib/src/preferences/preferences_impl.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; +import 'package:fluttery/preferences/preferences.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class PreferencesImpl implements Preferences { + final SharedPreferences _prefs; + + /// Constructor + PreferencesImpl({required SharedPreferences instance}) : _prefs = instance; + + @override + Future setString(String key, String value) async { + await _prefs.setString(key, value); + } + + @override + Future getString(String key) async { + return _prefs.getString(key); + } + + @override + Future setInt(String key, int value) async { + await _prefs.setInt(key, value); + } + + @override + Future getInt(String key) async { + return _prefs.getInt(key); + } + + @override + Future setBool(String key, bool value) async { + await _prefs.setBool(key, value); + } + + @override + Future getBool(String key) async { + return _prefs.getBool(key); + } + + @override + Future setDouble(String key, double value) async { + await _prefs.setDouble(key, value); + } + + @override + Future getDouble(String key) async { + return _prefs.getDouble(key); + } + + @override + Future setStringList(String key, List value) async { + await _prefs.setStringList(key, value); + } + + @override + Future?> getStringList(String key) async { + return _prefs.getStringList(key); + } + + @override + Future remove(String key) async { + await _prefs.remove(key); + } + + @override + Future clear() async { + await _prefs.clear(); + } +} diff --git a/finlog_app/fluttery/pubspec.yaml b/finlog_app/fluttery/pubspec.yaml index 316de94..9493003 100644 --- a/finlog_app/fluttery/pubspec.yaml +++ b/finlog_app/fluttery/pubspec.yaml @@ -14,6 +14,7 @@ dependencies: kiwi: ^5.0.1 logging: ^1.3.0 mocktail: ^1.0.4 + shared_preferences: ^2.5.3 dev_dependencies: flutter_test: diff --git a/finlog_app/fluttery/test/preferences/preferences_test.dart b/finlog_app/fluttery/test/preferences/preferences_test.dart new file mode 100644 index 0000000..3ce409c --- /dev/null +++ b/finlog_app/fluttery/test/preferences/preferences_test.dart @@ -0,0 +1,177 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:fluttery/src/preferences/preferences_impl.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +void main() { + late PreferencesImpl preferences; + + setUp(() async { + // Clear any existing data and set up a fresh in-memory instance + SharedPreferences.setMockInitialValues({}); + + // Create preferences instance that will use the real SharedPreferences + // but with in-memory storage for testing + final sharedInstance = await SharedPreferences.getInstance(); + preferences = PreferencesImpl(instance: sharedInstance); + + // Give time for initialization + await Future.delayed(Duration.zero); + }); + + group('PreferencesImpl Tests', () { + test('setString and getString work with real implementation', () async { + const key = 'testKey'; + const value = 'testValue'; + + await preferences.setString(key, value); + final result = await preferences.getString(key); + + expect(result, value); + }); + + test('setInt and getInt work with real implementation', () async { + const key = 'testKey'; + const value = 42; + + await preferences.setInt(key, value); + final result = await preferences.getInt(key); + + expect(result, value); + }); + + test('setBool and getBool work with real implementation', () async { + const key = 'testKey'; + const value = true; + + await preferences.setBool(key, value); + final result = await preferences.getBool(key); + + expect(result, value); + }); + + test('setDouble and getDouble work with real implementation', () async { + const key = 'testKey'; + const value = 3.14; + + await preferences.setDouble(key, value); + final result = await preferences.getDouble(key); + + expect(result, value); + }); + + test( + 'setStringList and getStringList work with real implementation', + () async { + const key = 'testKey'; + const value = ['one', 'two', 'three']; + + await preferences.setStringList(key, value); + final result = await preferences.getStringList(key); + + expect(result, value); + }, + ); + + test('remove deletes key-value pair', () async { + const key = 'testKey'; + const value = 'testValue'; + + // Set a value first + await preferences.setString(key, value); + expect(await preferences.getString(key), value); + + // Remove it + await preferences.remove(key); + final result = await preferences.getString(key); + + expect(result, isNull); + }); + + test('clear removes all data', () async { + // Set multiple values + await preferences.setString('key1', 'value1'); + await preferences.setInt('key2', 42); + await preferences.setBool('key3', true); + + // Verify they exist + expect(await preferences.getString('key1'), 'value1'); + expect(await preferences.getInt('key2'), 42); + expect(await preferences.getBool('key3'), true); + + // Clear all + await preferences.clear(); + + // Verify they're gone + expect(await preferences.getString('key1'), isNull); + expect(await preferences.getInt('key2'), isNull); + expect(await preferences.getBool('key3'), isNull); + }); + + test('getting non-existent keys returns null', () async { + expect(await preferences.getString('nonExistent'), isNull); + expect(await preferences.getInt('nonExistent'), isNull); + expect(await preferences.getBool('nonExistent'), isNull); + expect(await preferences.getDouble('nonExistent'), isNull); + expect(await preferences.getStringList('nonExistent'), isNull); + }); + + test('can overwrite existing values of the same type', () async { + const key = 'testKey'; + const initialValue = 'initialValue'; + const newValue = 'newValue'; + + await preferences.setString(key, initialValue); + expect(await preferences.getString(key), initialValue); + + await preferences.setString(key, newValue); + expect(await preferences.getString(key), newValue); + }); + + test( + 'different keys can store different data types simultaneously', + () async { + await preferences.setString('stringKey', 'value'); + await preferences.setInt('intKey', 42); + await preferences.setBool('boolKey', true); + await preferences.setDouble('doubleKey', 3.14); + await preferences.setStringList('listKey', ['a', 'b', 'c']); + + expect(await preferences.getString('stringKey'), 'value'); + expect(await preferences.getInt('intKey'), 42); + expect(await preferences.getBool('boolKey'), true); + expect(await preferences.getDouble('doubleKey'), 3.14); + expect(await preferences.getStringList('listKey'), ['a', 'b', 'c']); + }, + ); + + test('values can be overwritten with different data types', () async { + const key = 'testKey'; + + // Store a string value + await preferences.setString(key, 'stringValue'); + expect(await preferences.getString(key), 'stringValue'); + + // Overwrite with an int - this replaces the string value + await preferences.setInt(key, 42); + expect(await preferences.getInt(key), 42); + + // Overwrite with a bool - this replaces the int value + await preferences.setBool(key, true); + expect(await preferences.getBool(key), true); + }); + + test('persistence works across multiple operations', () async { + // Test that values persist through multiple set/get operations + await preferences.setString('key1', 'value1'); + await preferences.setInt('key2', 100); + + expect(await preferences.getString('key1'), 'value1'); + expect(await preferences.getInt('key2'), 100); + + // Modify one value and ensure the other remains + await preferences.setString('key1', 'newValue1'); + expect(await preferences.getString('key1'), 'newValue1'); + expect(await preferences.getInt('key2'), 100); + }); + }); +}