Files
buzz/mobile/test/widget_test.dart
klopez4212 f7708d0694 Polish mobile onboarding and profile setup (#8438)
Originally stacked on #8375, now merged. Rebased onto main.

Polishes the onboarding landing page, community-link entry, and recovery
sheets. Profile setup uses a consistent sheet with a larger avatar,
inline display name, and draft photo/emoji/animated editing; iOS uses
native controls and coordinated avatar/sheet transitions.

Validation: mobile analysis, full tests, and normal pre-push checks
passed after rebase. Prior iOS build and device walkthrough passed;
native validation was not repeated after this rebase. Snapshots omitted
as requested.

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Tom Brow <tomb@block.xyz>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz>
Co-authored-by: Tom Brow <tomb@block.xyz>
2026-10-22 17:27:38 +00:00

133 lines
4.0 KiB
Dart

import 'package:buzz/shared/hosted/hosted_environment.dart';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:buzz/shared/community/paired_community_landing.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:buzz/app.dart';
import 'package:buzz/features/age_gate/age_signal_provider.dart';
import 'package:buzz/shared/auth/auth.dart';
import 'package:buzz/shared/theme/theme_provider.dart';
void main() {
testWidgets('pairing loading cover blocks hidden input and semantics', (
tester,
) async {
SharedPreferences.setMockInitialValues({});
final prefs = await SharedPreferences.getInstance();
final container = ProviderContainer(
overrides: [
authProvider.overrideWith(() => _FakeAuthNotifier()),
ageSignalProvider.overrideWith(() => _AllowedAgeSignalNotifier()),
savedPrefsProvider.overrideWithValue(prefs),
],
);
addTearDown(container.dispose);
final semantics = tester.ensureSemantics();
String semanticsTree() => tester
.binding
.renderViews
.single
.owner!
.semanticsOwner!
.rootSemanticsNode!
.toStringDeep();
await tester.pumpWidget(
UncontrolledProviderScope(container: container, child: const App()),
);
await tester.pump();
var taps = 0;
final navigator = tester.state<NavigatorState>(
find.byType(Navigator).first,
);
unawaited(
navigator.push(
MaterialPageRoute<void>(
builder: (_) => Scaffold(
body: Align(
alignment: Alignment.topLeft,
child: TextButton(
onPressed: () => taps++,
child: const Text('Hidden action'),
),
),
),
),
),
);
await tester.pumpAndSettle();
final button = find.text('Hidden action');
final location = tester.getCenter(button);
expect(semanticsTree(), contains('Hidden action'));
container
.read(pairedCommunityLandingProvider.notifier)
.request(
Community(
id: 'test',
addedAt: DateTime(2026),
name: 'Test',
relayUrl: 'https://relay.test',
),
);
await tester.pump();
await tester.tapAt(location);
expect(taps, 0);
expect(semanticsTree(), isNot(contains('Hidden action')));
container.read(pairedCommunityLandingProvider.notifier).clear();
await tester.pump();
expect(semanticsTree(), contains('Hidden action'));
await tester.tapAt(location);
expect(taps, 1);
await tester.pumpWidget(const SizedBox.shrink());
semantics.dispose();
});
testWidgets('App renders pairing page when unauthenticated', (
WidgetTester tester,
) async {
SharedPreferences.setMockInitialValues({});
final prefs = await SharedPreferences.getInstance();
await tester.pumpWidget(
ProviderScope(
overrides: [
authProvider.overrideWith(() => _FakeAuthNotifier()),
ageSignalProvider.overrideWith(() => _AllowedAgeSignalNotifier()),
savedPrefsProvider.overrideWithValue(prefs),
],
child: const App(),
),
);
await tester.pump();
expect(find.bySemanticsLabel('Buzz'), findsOneWidget);
expect(
find.text('Sign in with builderlab'),
HostedEnvironment.enabled ? findsOneWidget : findsNothing,
);
expect(
find.text('Other options'),
HostedEnvironment.enabled ? findsOneWidget : findsNothing,
);
expect(
find.text('Scan a QR code'),
HostedEnvironment.enabled ? findsNothing : findsOneWidget,
);
});
}
class _AllowedAgeSignalNotifier extends AgeSignalNotifier {
@override
AgeSignalState build() => AgeSignalState.allowed;
@override
Future<void> request() async {}
}
class _FakeAuthNotifier extends AuthNotifier {
@override
Future<AuthState> build() async {
return const AuthState(status: AuthStatus.unauthenticated);
}
}