mirror of
https://github.com/block/buzz.git
synced 2026-11-13 04:41:12 +00:00
New mobile communities currently require a manual Settings opt-in before push can start. Default that local preference to on for new communities and stored records without a preference. Preserve every saved `true` or `false`, including values written by older clients. Older default-off values are indistinguishable from explicit opt-outs, so this does not migrate them to on. Push still requires a configured gateway, authenticated connectivity, and a valid relay capability. iOS continues to control display authorization through its existing permission prompt. Notification eligibility and subscriptions are unchanged. Settings retains its existing opt-out control for enabled communities even when capability is unavailable. Drafted from the 0.24 baseline; release-branch inclusion is a separate decision. ### Related issue Closest related issue: #3238 (synced defaults). This change is limited to the mobile device-local community preference; no duplicate found. ### Validation - Added or updated coverage for new and missing preferences, saved true/false persistence, opt-out after restart, capability-gated registration, and Settings without a configured gateway. - Full configured mobile suite: 3,499 passed, 4 skipped. Separate no-gateway suite: 4 passed. Flutter analysis passed. - Existing permission-denied and unsupported-relay tests passed as part of the mobile suite. No physical-device or end-to-end APNs validation performed. - Full local repository gate passed (formatting, lint, unit tests, desktop/web builds, Tauri checks/tests, and mobile tests). - Follow-up review edits: restored the original VISION.md wording and shared the default in one private Community constant. All 43 focused community/bootstrap tests passed. <!-- buzz-review-completed --> --------- Signed-off-by: Tom Brow <tomb@block.xyz>
94 lines
2.9 KiB
Dart
94 lines
2.9 KiB
Dart
import 'package:buzz/shared/community/community.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
void main() {
|
|
test('existing records default to device authentication', () {
|
|
final community = Community.fromJson({
|
|
'id': 'one',
|
|
'name': 'Buzz',
|
|
'relayUrl': 'https://relay.test',
|
|
'addedAt': '2026-08-05T00:00:00.000Z',
|
|
});
|
|
|
|
expect(
|
|
community.sensitiveActionPolicy,
|
|
SensitiveActionPolicy.disabledByUser,
|
|
);
|
|
expect(community.starterSetupIncomplete, isFalse);
|
|
expect(community.pushLeaseInstallationId, isNull);
|
|
expect(community.pushNotificationsEnabled, isTrue);
|
|
expect(community.pushSubscriptionState.pendingTombstoneGeneration, isNull);
|
|
});
|
|
|
|
test('new community gets a unique canonical push lease address id', () {
|
|
final first = Community.create(name: 'One', relayUrl: 'https://relay.test');
|
|
final second = Community.create(
|
|
name: 'Two',
|
|
relayUrl: 'https://relay.test',
|
|
);
|
|
|
|
expect(first.pushNotificationsEnabled, isTrue);
|
|
expect(Community.fromJson(first.toJson()).pushNotificationsEnabled, isTrue);
|
|
expect(first.pushLeaseInstallationId, matches(RegExp(r'^[0-9a-f]{32}$')));
|
|
expect(
|
|
second.pushLeaseInstallationId,
|
|
isNot(first.pushLeaseInstallationId),
|
|
);
|
|
});
|
|
|
|
test('community settings round trip', () {
|
|
final community = Community(
|
|
id: 'one',
|
|
name: 'Buzz',
|
|
relayUrl: 'https://relay.test',
|
|
sensitiveActionPolicy: SensitiveActionPolicy.enabled,
|
|
pushLeaseInstallationId: 'a' * 32,
|
|
starterSetupIncomplete: true,
|
|
addedAt: DateTime.utc(2026, 8, 5),
|
|
);
|
|
|
|
final roundTrip = Community.fromJson(community.toJson());
|
|
expect(roundTrip.sensitiveActionPolicy, SensitiveActionPolicy.enabled);
|
|
expect(roundTrip.starterSetupIncomplete, isTrue);
|
|
expect(roundTrip.pushLeaseInstallationId, 'a' * 32);
|
|
});
|
|
|
|
for (final enabled in [true, false]) {
|
|
test('saved push preference $enabled survives loading and copying', () {
|
|
final community = Community.fromJson({
|
|
'id': 'one',
|
|
'name': 'Buzz',
|
|
'relayUrl': 'https://relay.test',
|
|
'pushNotificationsEnabled': enabled,
|
|
'addedAt': '2026-08-05T00:00:00.000Z',
|
|
});
|
|
expect(community.pushNotificationsEnabled, enabled);
|
|
expect(
|
|
community.copyWith(name: 'Renamed').pushNotificationsEnabled,
|
|
enabled,
|
|
);
|
|
expect(
|
|
Community.fromJson(community.toJson()).pushNotificationsEnabled,
|
|
enabled,
|
|
);
|
|
expect(
|
|
community.pushSubscriptionState.pendingTombstoneGeneration,
|
|
isNull,
|
|
);
|
|
});
|
|
}
|
|
|
|
test('malformed stored push lease address id is rejected', () {
|
|
expect(
|
|
() => Community.fromJson({
|
|
'id': 'one',
|
|
'name': 'Buzz',
|
|
'relayUrl': 'https://relay.test',
|
|
'pushLeaseInstallationId': 'not-canonical',
|
|
'addedAt': '2026-08-05T00:00:00.000Z',
|
|
}),
|
|
throwsFormatException,
|
|
);
|
|
});
|
|
}
|