Skip to content

Commit a765638

Browse files
authored
fix: method "keys" returns an immutable copy of the cache keys (#166)
Closes #165
1 parent 27b77a1 commit a765638

16 files changed

+219
-102
lines changed

CHANGELOG.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Method "keys" for listing all cache keys —
13+
[152](https://github.com/dartoos-dev/json_cache/issues/152)
14+
1015
### Changed
1116

12-
- update linting rules —
17+
- Mehtod "keys" returns an immutable copy of the underlying cache keys —
18+
[165](https://github.com/dartoos-dev/json_cache/issues/152)
19+
20+
- Update linting rules —
1321
[162](https://github.com/dartoos-dev/json_cache/issues/154).
1422

15-
1623
## [3.0.2] - 2024-08-19
1724

1825
### Changed
1926

20-
- Bump up dependencies —
27+
- Updated dependencies —
2128
[154](https://github.com/dartoos-dev/json_cache/issues/154).
2229

2330
### Fixed
2431

25-
- Removed code warnings and upgraded dart SDK range and each dependency to latest resolvable version available - [148](https://github.com/dartoos-dev/json_cache/issues/148).
32+
- Remove code warnings and upgrade the dart SDK range. In addition,
33+
dependencies were updated to the latest resolvable version —
34+
[148](https://github.com/dartoos-dev/json_cache/issues/148).
2635

2736
## [3.0.1] - 2023-08-10
2837

2938
### Fixed
3039

31-
- removed unused package 'cross_local_storage' from pubspec —
40+
- Removed unused package 'cross_local_storage' from pubspec —
3241
[144](https://github.com/dartoos-dev/json_cache/issues/144).
3342

3443
## [3.0.0] - 2023-08-10
3544

3645
### Removed
3746

38-
- support for the 'cross_local_storage' package — **BREAKING CHANGE**
47+
- Support for the 'cross_local_storage' package — **BREAKING CHANGE**
3948
[140](https://github.com/dartoos-dev/json_cache/issues/140).
4049

4150
### Fixed

lib/src/json_cache.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ abstract class JsonCache {
2828
/// Returns `true` if there is cached data at [key]; `false` otherwise.
2929
Future<bool> contains(String key);
3030

31-
/// Lists all keys.
31+
/// The cache keys.
3232
///
33-
/// Returns an **unmodifiable** list of cache keys without duplicates.
33+
/// Returns an **unmodifiable** list of all cache keys without duplicates.
3434
Future<UnmodifiableListView<String>> keys();
3535
}

lib/src/json_cache_fake.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,6 @@ class JsonCacheFake implements JsonCache {
5555

5656
@override
5757
Future<UnmodifiableListView<String>> keys() async {
58-
return UnmodifiableListView(_memory.keys);
58+
return UnmodifiableListView(List.unmodifiable(_memory.keys));
5959
}
6060
}

lib/src/json_cache_hive.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class JsonCacheHive implements JsonCache {
4141

4242
@override
4343
Future<UnmodifiableListView<String>> keys() async {
44-
return UnmodifiableListView(_box.keys.map((k) => k as String));
44+
return UnmodifiableListView(
45+
_box.keys.map((k) => k as String).toList(growable: false),
46+
);
4547
}
4648
}

lib/src/json_cache_mem.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ class JsonCacheMem implements JsonCache {
161161
@override
162162
Future<UnmodifiableListView<String>> keys() {
163163
return _mutex.protectRead(() async {
164-
return UnmodifiableListView(_memory.keys);
164+
return UnmodifiableListView(_memory.keys.toList(growable: false));
165165
});
166166
}
167167
}

lib/src/json_cache_safe_local_storage.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,8 @@ class JsonCacheSafeLocalStorage implements JsonCache {
4747

4848
@override
4949
Future<UnmodifiableListView<String>> keys() async {
50-
final data = await _cachedData;
5150
return UnmodifiableListView(
52-
data.keys.map((k) => k as String),
51+
(await _cachedData).keys.map((k) => k as String),
5352
);
5453
}
5554

test/json_cache_fake_test.dart

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'package:flutter_test/flutter_test.dart';
22
import 'package:json_cache/json_cache.dart';
33

44
void main() {
5-
group('JsonCacheFake', () {
5+
group('JsonCacheFake:', () {
66
const profKey = 'profile';
77
const prefKey = 'preferences';
88
const profData = <String, dynamic>{'id': 1, 'name': 'John Due'};
@@ -65,13 +65,24 @@ void main() {
6565
expect(await fake.contains(prefKey), false);
6666
expect(await fake.contains('a key'), false);
6767
});
68-
test('keys', () async {
69-
final fake = JsonCacheFake();
70-
// update data
71-
await fake.refresh(profKey, profData);
72-
await fake.refresh(prefKey, prefData);
73-
74-
expect(await fake.keys(), [profKey, prefKey]);
68+
group('method "keys"', () {
69+
late JsonCacheFake fakeCache;
70+
setUp(() async {
71+
fakeCache = JsonCacheFake();
72+
// update data
73+
await fakeCache.refresh(profKey, profData);
74+
await fakeCache.refresh(prefKey, prefData);
75+
});
76+
test('should return the inserted keys', () async {
77+
expect(await fakeCache.keys(), [profKey, prefKey]);
78+
});
79+
test('should keep the returned keys immutable', () async {
80+
final keys = await fakeCache.keys();
81+
// This should not change the 'keys' variable.
82+
await fakeCache
83+
.refresh('info', {'This is very important information.': true});
84+
expect(keys, [profKey, prefKey]);
85+
});
7586
});
7687
group('remove', () {
7788
test('default ctor', () async {

test/json_cache_flutter_secure_storage_test.dart

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import 'package:json_cache/json_cache.dart';
44
import 'flutter_secure_storage_mock.dart';
55

66
void main() {
7-
group('JsonCacheFlutterSecureStorage', () {
7+
group('JsonCacheFlutterSecureStorage:', () {
88
const profKey = 'profile';
99
const prefKey = 'preferences';
1010
const profData = <String, dynamic>{'id': 1, 'name': 'John Due'};
@@ -50,15 +50,26 @@ void main() {
5050
await flutterSecureCache.remove(prefKey);
5151
expect(await flutterSecureCache.contains(prefKey), false);
5252
});
53-
test('keys', () async {
54-
final secStorageMock = FlutterSecureStorageMock();
55-
final JsonCacheFlutterSecureStorage flutterSecureCache =
56-
JsonCacheFlutterSecureStorage(secStorageMock);
57-
// update data
58-
await flutterSecureCache.refresh(profKey, profData);
59-
await flutterSecureCache.refresh(prefKey, prefData);
6053

61-
expect(await flutterSecureCache.keys(), [profKey, prefKey]);
54+
group('method "keys"', () {
55+
late JsonCacheFlutterSecureStorage flutterSecureCache;
56+
setUp(() async {
57+
flutterSecureCache =
58+
JsonCacheFlutterSecureStorage(FlutterSecureStorageMock());
59+
// update data
60+
await flutterSecureCache.refresh(profKey, profData);
61+
await flutterSecureCache.refresh(prefKey, prefData);
62+
});
63+
test('should return the inserted keys', () async {
64+
expect(await flutterSecureCache.keys(), [profKey, prefKey]);
65+
});
66+
test('should keep the returned keys immutable', () async {
67+
final keys = await flutterSecureCache.keys();
68+
// This should not change the 'keys' variable.
69+
await flutterSecureCache
70+
.refresh('info', {'This is very important information.': true});
71+
expect(keys, [profKey, prefKey]);
72+
});
6273
});
6374
test('remove', () async {
6475
final secStorageMock = FlutterSecureStorageMock();

test/json_cache_hive_test.dart

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ void main() {
1010
tearDown(() async {
1111
await tearDownTestHive();
1212
});
13-
group('JsonCacheHive', () {
13+
group('JsonCacheHive:', () {
1414
const profKey = 'profile';
1515
const prefKey = 'preferences';
1616
const profData = <String, dynamic>{'id': 1, 'name': 'John Due'};
@@ -47,15 +47,25 @@ void main() {
4747
await hiveCache.remove(prefKey);
4848
expect(await hiveCache.contains(prefKey), false);
4949
});
50-
51-
test('keys', () async {
52-
final box = await Hive.openBox<String>('test-contains-method');
53-
final JsonCacheHive hiveCache = JsonCacheHive(box);
54-
// update data
55-
await hiveCache.refresh(profKey, profData);
56-
await hiveCache.refresh(prefKey, prefData);
57-
58-
expect(await hiveCache.keys(), [prefKey, profKey]);
50+
group('method "keys"', () {
51+
late JsonCacheHive hiveCache;
52+
setUp(() async {
53+
final box = await Hive.openBox<String>('test-keys-method');
54+
hiveCache = JsonCacheHive(box);
55+
// update data
56+
await hiveCache.refresh(profKey, profData);
57+
await hiveCache.refresh(prefKey, prefData);
58+
});
59+
test('should return the inserted keys', () async {
60+
expect(await hiveCache.keys(), [prefKey, profKey]);
61+
});
62+
test('should keep the returned keys immutable', () async {
63+
final keys = await hiveCache.keys();
64+
// This should not change the 'keys' variable.
65+
await hiveCache
66+
.refresh('info', {'This is very important information.': true});
67+
expect(keys, [prefKey, profKey]);
68+
});
5969
});
6070
test('remove', () async {
6171
final box = await Hive.openBox<String>('test-remove');

test/json_cache_hollow_test.dart

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'package:flutter_test/flutter_test.dart';
22
import 'package:json_cache/json_cache.dart';
33

44
void main() {
5-
group('JsonCacheHollow', () {
5+
group('JsonCacheHollow:', () {
66
const profKey = 'profile';
77
const prefKey = 'preferences';
88
const profData = <String, dynamic>{'id': 1, 'name': 'John Due'};
@@ -36,11 +36,17 @@ void main() {
3636
expect(await fake.contains('a key'), false);
3737
});
3838
test('keys', () async {
39-
const fake = JsonCacheHollow();
40-
await fake.refresh(profKey, profData);
41-
await fake.refresh(prefKey, prefData);
39+
const hollowCache = JsonCacheHollow();
40+
await hollowCache.refresh(profKey, profData);
41+
await hollowCache.refresh(prefKey, prefData);
42+
43+
final keys = await hollowCache.keys();
44+
expect(keys, const []);
4245

43-
expect(await fake.keys(), const []);
46+
// This should not change the 'keys' variable.
47+
await hollowCache
48+
.refresh('info', {'This is very important information.': true});
49+
expect(keys, const []);
4450
});
4551
test('remove', () async {
4652
const JsonCacheHollow hollowCache = JsonCacheHollow();

0 commit comments

Comments
 (0)