Files
buzz/mobile/test/features/agents/remote_agent_model_control_test.dart
klopez4212 0cde1fe2f4 Make mobile Agents a full-page owned-agent directory (#8693)
Replace the mobile Agents sheet with a full-page directory of verified
owned agents. Add dedicated creation and avatar pages with
catalog-backed model selection, reuse the profile emoji/photo/camera
controls, and expose Builderbot model settings while labeling desktop
agents “Manage on desktop.” Share one account-scoped model catalog
across editable cards and retries. Choose Bestie from the agent profile
using the shared encrypted main-agent record (text-only action, filled
star once selected), and move confirmed deletion to a top-left trash
control with native iOS glass. Include uploaded avatars in owner
registrations so desktop can display them.

Validation: mobile analysis and all 3,958 hosted-enabled app tests
passed; default-build tests run by the push hook. Earlier iPhone build
installed and iterated with the user; the current iOS build succeeds,
but final changes still need a device pass. Independent review found no
new blockers. Actual camera capture and live Bestie sync remain
unconfirmed; the existing shared `main-agent` wire format and Bestie
terminology are retained.

### Snapshots

Widget-harness captures with test data (not native iOS chrome).

| Agents directory | Image avatar editor |
| --- | --- |
| ![Agents
directory](https://github.com/user-attachments/assets/c68a0505-90a5-41db-980f-e3197cac63ac)
| ![Image avatar
editor](https://github.com/user-attachments/assets/9b126186-1e7c-4169-9a74-8f7f252cfa93)
|

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz>
2026-10-29 18:30:17 +00:00

100 lines
3.3 KiB
Dart

import 'dart:async';
import 'package:buzz/features/agents/remote_agent_model_control.dart';
import 'package:buzz/shared/community/community.dart';
import 'package:buzz/shared/theme/theme.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../helpers/remote_agents_fixture.dart';
void main() {
testWidgets('cards share catalog loading, retry, and account transitions', (
tester,
) async {
tester.view.physicalSize = const Size(390, 1600);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
final registry = FakeRegistry();
final controller = RelayFakeController(registry);
addTearDown(() {
controller.dispose();
controller.relayAuth.dispose();
registry.dispose();
});
final community = Community.create(
name: 'Test',
relayUrl: 'wss://test.example',
);
final gate = Completer<void>();
registry.catalogGate = gate;
int requests() =>
registry.calls.where((call) => call == 'get-model-catalog').length;
Future<void> render(int count) => tester.pumpWidget(
ProviderScope(
child: MaterialApp(
theme: AppTheme.light(),
home: Scaffold(
body: Column(
children: [
for (var i = 0; i < count; i++)
RemoteAgentModelControl(
controller: controller,
agent: {'agent_pubkey': '$i', 'model_id': 'test-model'},
community: community,
isCurrent: () => true,
),
],
),
),
),
),
);
await render(15);
await tester.pump();
expect(requests(), 1);
expect(find.byType(CircularProgressIndicator), findsNWidgets(15));
gate.completeError(StateError('Unavailable'));
await tester.pumpAndSettle();
expect(find.text('Retry models'), findsNWidgets(15));
expect(requests(), 1);
registry.catalogGate = null;
await tester.tap(find.text('Retry models').first);
await tester.pumpAndSettle();
expect(requests(), 2);
expect(find.text('Test model'), findsNWidgets(15));
// A later-mounted card uses the same result, not another queued call.
await render(16);
await tester.pumpAndSettle();
expect(requests(), 2);
expect(find.text('Test model'), findsNWidgets(16));
final next = Completer<void>();
registry.catalogGate = next;
registry.subject = 'another-owner';
await tester.pump();
await tester.pump();
expect(requests(), 3);
expect(find.text('Test model'), findsNothing);
expect(find.byType(CircularProgressIndicator), findsNWidgets(16));
// Signing out while that request is pending cannot restore its result.
registry.signedIn = false;
await tester.pumpAndSettle();
expect(find.text('Retry models'), findsNWidgets(16));
next.complete();
await tester.pumpAndSettle();
expect(find.text('Test model'), findsNothing);
expect(requests(), 3);
registry.catalogGate = null;
registry.signedIn = true;
await tester.pumpAndSettle();
expect(requests(), 4);
expect(find.text('Test model'), findsNWidgets(16));
expect(tester.takeException(), isNull);
});
}