import 'package:flutter_test/flutter_test.dart'; import 'package:tane/security/secret_store.dart'; import 'package:tane/services/social_settings.dart'; /// In-memory [SecretStore] for tests. class FakeSecretStore implements SecretStore { final Map _data = {}; @override Future read(String key) async => _data[key]; @override Future write(String key, String value) async => _data[key] = value; } void main() { late SocialSettings settings; setUp(() => settings = SocialSettings(FakeSecretStore())); test('defaults: empty area, but relays fall back to the defaults', () async { expect(await settings.areaGeohash(), ''); expect(await settings.relayUrls(), SocialSettings.defaultRelays); // Not configured yet: the area is still unset. expect(await settings.isConfigured, isFalse); }); test('an explicitly empty relay choice turns the network off', () async { await settings.setRelayUrls(const []); expect(await settings.relayUrls(), isEmpty); }); test('stores and normalises the area geohash (trim + lowercase)', () async { await settings.setAreaGeohash(' SP3E9 '); expect(await settings.areaGeohash(), 'sp3e9'); }); test('stores relay urls, dropping blanks', () async { await settings.setRelayUrls([ 'wss://relay.comunes.org', ' ', 'wss://seeds.example.org', ]); expect(await settings.relayUrls(), ['wss://relay.comunes.org', 'wss://seeds.example.org']); }); test('is configured once an area is set (relays are defaulted)', () async { expect(await settings.isConfigured, isFalse); // no area yet await settings.setAreaGeohash('sp3e9'); expect(await settings.isConfigured, isTrue); }); test('search precision defaults to 4 (a wide "around here")', () async { expect(await settings.searchPrecision(), 4); }); test('stores and reads back the search precision', () async { await settings.setSearchPrecision(3); expect(await settings.searchPrecision(), 3); await settings.setSearchPrecision(5); expect(await settings.searchPrecision(), 5); }); test('search precision is clamped to the 3–5 range', () async { await settings.setSearchPrecision(1); expect(await settings.searchPrecision(), 3); await settings.setSearchPrecision(9); expect(await settings.searchPrecision(), 5); }); test('a corrupt stored precision falls back to the default', () async { final store = FakeSecretStore(); await store.write('tane.social.search_precision', 'oops'); expect(await SocialSettings(store).searchPrecision(), 4); }); test('the blocklist starts empty and round-trips block/unblock', () async { expect(await settings.blockedPubkeys(), isEmpty); await settings.block('AB' * 32); expect(await settings.isBlocked('ab' * 32), isTrue); // normalised expect(await settings.blockedPubkeys(), {'ab' * 32}); await settings.block('cd' * 32); expect(await settings.blockedPubkeys(), hasLength(2)); await settings.unblock('ab' * 32); expect(await settings.isBlocked('ab' * 32), isFalse); expect(await settings.blockedPubkeys(), {'cd' * 32}); }); test('blocking twice keeps a single entry', () async { await settings.block('ab' * 32); await settings.block(' AB' * 1 + 'ab' * 31); // messy spacing/case expect(await settings.blockedPubkeys(), hasLength(1)); }); test('hidden (reported) offers round-trip as author:id keys', () async { expect(await settings.hiddenOfferKeys(), isEmpty); await settings.hideOffer(authorPubkeyHex: 'AB' * 32, offerId: 'tomate-1'); expect( await settings.hiddenOfferKeys(), {SocialSettings.offerKey('ab' * 32, 'tomate-1')}, ); }); }