// Workspace switcher — stage-1 contract: the control renders the // active selection, lists "All projects" plus every registry // project (colour dot, shield for protected), and switching // updates the shared Workspace notifier. import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:chain_studio/data/hub.dart'; import 'package:chain_studio/data/workspace.dart'; import 'package:chain_studio/l10n/app_localizations.dart'; import 'package:chain_studio/widgets/chain_workspace_switcher.dart'; Widget _host() { return const MaterialApp( localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, home: Scaffold( appBar: PreferredSize( preferredSize: Size.fromHeight(kToolbarHeight), child: Material(child: ChainWorkspaceSwitcher()), ), body: SizedBox(), ), ); } const _general = ProjectRef(slug: 'general', name: 'General'); const _clientA = ProjectRef( slug: 'client-a', name: 'Client A', color: '#8b7cf6', isolation: 'protected', ); void main() { setUp(() { // Seed the singleton without a hub: tests drive the notifier // directly through its test hook. Workspace.instance.debugSeed(projects: [_general, _clientA], active: ''); }); testWidgets('shows "All projects" when no project is active', ( tester, ) async { await tester.pumpWidget(_host()); expect(find.text('All projects'), findsOneWidget); }); testWidgets('menu lists all-projects entry plus every registry project', ( tester, ) async { await tester.pumpWidget(_host()); await tester.tap(find.byType(ChainWorkspaceSwitcher)); await tester.pumpAndSettle(); expect(find.text('All projects'), findsWidgets); expect(find.text('General'), findsOneWidget); expect(find.text('Client A'), findsOneWidget); // Protected projects carry the shield marker. expect(find.byIcon(Icons.shield_outlined), findsOneWidget); }); testWidgets('selecting a project updates the workspace and the label', ( tester, ) async { await tester.pumpWidget(_host()); await tester.tap(find.byType(ChainWorkspaceSwitcher)); await tester.pumpAndSettle(); await tester.tap(find.text('Client A').last); await tester.pumpAndSettle(); expect(Workspace.instance.activeSlug, 'client-a'); expect(Workspace.instance.active?.isProtected, isTrue); // The closed control now shows the active project (label + // shield marker for protected). expect(find.text('Client A'), findsOneWidget); expect(find.byIcon(Icons.shield_outlined), findsOneWidget); }); test('active falls back to null when the slug left the registry', () { Workspace.instance.debugSeed(projects: [_general], active: 'gone'); expect(Workspace.instance.activeSlug, 'gone'); expect(Workspace.instance.active, isNull); expect(Workspace.instance.isAll, isFalse); }); }