iop/packages/flutter/iop_console/test/iop_console_shell_test.dart

231 lines
7.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:iop_console/iop_console.dart';
void main() {
Future<void> pumpConsole(
WidgetTester tester, {
required Size viewport,
Widget? executionLogs,
IopConsoleConfig? config,
IopConsoleThemeAdapter? themeAdapter,
IopConsoleNavigationCallback? onNavigate,
IopCapabilityPack? capabilities,
}) async {
tester.view.physicalSize = viewport;
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
await tester.pumpWidget(
MaterialApp(
home: IopConsoleShell(
overview: const Center(child: Text('Overview content')),
executionLogs: executionLogs,
config: config,
themeAdapter: themeAdapter,
onNavigate: onNavigate,
capabilities: capabilities,
),
),
);
}
testWidgets('public shell renders without an app-owned console wrapper', (
tester,
) async {
await pumpConsole(tester, viewport: const Size(1024, 768));
expect(find.text('Overview content'), findsOneWidget);
expect(find.byIcon(Icons.dashboard_outlined), findsOneWidget);
await tester.tap(find.byIcon(Icons.smart_toy_outlined));
await tester.pump();
expect(find.byType(IopAgentPanel), findsOneWidget);
expect(find.text('Ask about IOP operations'), findsOneWidget);
expect(tester.takeException(), isNull);
});
testWidgets('rail and content remain stable on narrow and wide viewports', (
tester,
) async {
for (final viewport in const [Size(320, 640), Size(1200, 800)]) {
await pumpConsole(tester, viewport: viewport);
expect(find.text('Overview content'), findsOneWidget);
expect(find.byIcon(Icons.tune), findsOneWidget);
expect(tester.getSize(find.byIcon(Icons.dashboard_outlined)).height, 24);
expect(tester.takeException(), isNull);
}
});
testWidgets(
'supports navigation to executionLogs and displays injected widget',
(tester) async {
var navigatedSection = IopConsoleSection.overview;
await pumpConsole(
tester,
viewport: const Size(1024, 768),
executionLogs: const Center(child: Text('Custom Logs Content')),
onNavigate: (section) => navigatedSection = section,
);
// Tap on Execution & Logs rail item
await tester.tap(find.byIcon(Icons.list_alt_outlined));
await tester.pump();
expect(navigatedSection, IopConsoleSection.executionLogs);
expect(find.text('Custom Logs Content'), findsOneWidget);
expect(tester.takeException(), isNull);
},
);
testWidgets('injects capabilities and displays them in IopAgentPanel', (
tester,
) async {
const pack = IopCapabilityPack(
capabilities: [
IopCapability(
name: 'Target Command Execution',
description: 'Run targeted terminal automation commands.',
),
IopCapability(
name: 'Session Maintenance',
description: 'Establish and clean up persistent CLI sessions.',
),
],
);
await pumpConsole(
tester,
viewport: const Size(1024, 768),
capabilities: pack,
);
// Go to Agent Tab
await tester.tap(find.byIcon(Icons.smart_toy_outlined));
await tester.pump();
// Verify capability details are visible in the introductory message text
expect(find.textContaining('Target Command Execution'), findsOneWidget);
expect(find.textContaining('Session Maintenance'), findsOneWidget);
expect(tester.takeException(), isNull);
});
testWidgets(
'IopConsoleOverview renders endpoints, status badge, and triggers refresh',
(tester) async {
tester.view.physicalSize = const Size(1024, 768);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
const config = IopConsoleConfig(
controlPlaneHttpUrl: 'https://api.iop.test',
controlPlaneWireUrl: 'wss://wire.iop.test',
authTokenReference: 'cp-auth-ref-main',
);
var refreshCount = 0;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: IopConsoleOverview(
config: config,
statusText: 'Connected to Control Plane',
onRefresh: () => refreshCount++,
),
),
),
);
// Check header and status badge
expect(find.text('Operations Overview'), findsOneWidget);
expect(find.text('CONNECTED TO CONTROL PLANE'), findsOneWidget);
// Check config values
expect(find.text('https://api.iop.test'), findsOneWidget);
expect(find.text('wss://wire.iop.test'), findsOneWidget);
// Check auth token reference key value
expect(find.text('cp-auth-ref-main'), findsOneWidget);
// Check refresh button functionality
final refreshBtn = find.text('Refresh Connection');
expect(refreshBtn, findsOneWidget);
await tester.tap(refreshBtn);
await tester.pump();
expect(refreshCount, 1);
expect(tester.takeException(), isNull);
},
);
testWidgets('IopConsoleOverview handles disconnected status correctly', (
tester,
) async {
tester.view.physicalSize = const Size(1024, 768);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
const config = IopConsoleConfig(
controlPlaneHttpUrl: 'https://api.iop.test',
controlPlaneWireUrl: 'wss://wire.iop.test',
);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: IopConsoleOverview(config: config, statusText: 'Disconnected'),
),
),
);
// Verify it displays OFFLINE status text and DISCONNECTED status badge
expect(find.text('DISCONNECTED'), findsOneWidget);
expect(find.text('OFFLINE'), findsOneWidget);
expect(tester.takeException(), isNull);
});
testWidgets(
'IopConsoleOverview preserves narrow and wide responsive sections',
(tester) async {
const config = IopConsoleConfig(
controlPlaneHttpUrl: 'https://api.iop.test',
controlPlaneWireUrl: 'wss://wire.iop.test',
authTokenReference: 'cp-auth-ref-main',
);
// 400px width drives the narrow (< 600) layout; 1024px drives the wide one.
for (final viewport in const [Size(400, 1200), Size(1024, 1200)]) {
tester.view.physicalSize = viewport;
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: IopConsoleOverview(
config: config,
statusText: 'Connected to Control Plane',
),
),
),
);
await tester.pump();
// Header, status badge, and endpoint sections render on both viewports.
expect(find.text('Operations Overview'), findsOneWidget);
expect(find.text('CONNECTED TO CONTROL PLANE'), findsOneWidget);
expect(find.text('SYSTEM ENDPOINTS'), findsOneWidget);
expect(find.text('https://api.iop.test'), findsOneWidget);
expect(find.text('wss://wire.iop.test'), findsOneWidget);
expect(tester.takeException(), isNull);
}
},
);
}