import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:nuvolari/core/region/region_config.dart'; import 'package:nuvolari/core/region/region_repository.dart'; import 'package:nuvolari/features/map/attribution_bar.dart'; import 'package:nuvolari/features/sources/sources_screen.dart'; import 'package:nuvolari/l10n/app_localizations.dart'; RegionConfig loadPiemonte() => RegionConfig.parse(File('assets/regions/piemonte.json').readAsStringSync()); Widget wrap(Widget child, RegionConfig region) => ProviderScope( overrides: [regionConfigProvider.overrideWith((ref) async => region)], child: MaterialApp( locale: const Locale('it'), localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, home: child, ), ); void main() { late RegionConfig region; setUpAll(() { region = loadPiemonte(); }); group('SourcesScreen', () { testWidgets('lists every configured source with its licence', ( tester, ) async { await tester.pumpWidget(wrap(const SourcesScreen(), region)); await tester.pumpAndSettle(); for (final attribution in region.attributions) { expect( find.text(attribution.text), findsOneWidget, reason: '${attribution.id} is missing from the Sources screen', ); } expect(find.textContaining('CC BY-SA'), findsWidgets); expect(find.textContaining('ODbL'), findsWidgets); }); // ARPA publishes no licence for the alert bulletin. Showing an invented one // would be worse than showing none, so the screen must say so explicitly. testWidgets('says when a source states no licence', (tester) async { await tester.pumpWidget(wrap(const SourcesScreen(), region)); await tester.pumpAndSettle(); expect(find.text('Nessuna licenza dichiarata dalla fonte'), findsWidgets); }); testWidgets('shows the independence disclaimer', (tester) async { await tester.pumpWidget(wrap(const SourcesScreen(), region)); await tester.pumpAndSettle(); expect(find.text('App non ufficiale'), findsOneWidget); expect(find.textContaining('indipendente'), findsOneWidget); }); testWidgets('explains the share-alike obligation', (tester) async { await tester.pumpWidget(wrap(const SourcesScreen(), region)); await tester.pumpAndSettle(); // Below the fold in the test viewport once the base-map credits are listed. await tester.scrollUntilVisible( find.text('Dati derivati'), 200, scrollable: find.byType(Scrollable).first, ); await tester.pumpAndSettle(); expect(find.text('Dati derivati'), findsOneWidget); expect(find.textContaining('CC BY-SA'), findsWidgets); }); testWidgets('links the official bulletin', (tester) async { await tester.pumpWidget(wrap(const SourcesScreen(), region)); await tester.pumpAndSettle(); // The button sits below the fold in the test viewport. await tester.scrollUntilVisible( find.text('Bollettino ufficiale Arpa Piemonte'), 200, scrollable: find.byType(Scrollable).first, ); await tester.pumpAndSettle(); expect(find.text('Bollettino ufficiale Arpa Piemonte'), findsOneWidget); }); }); group('AttributionBar', () { testWidgets('shows only the sources currently on screen', (tester) async { await tester.pumpWidget( wrap( Scaffold( body: AttributionBar( region: region, activeSourceIds: const {'osm'}, ), ), region, ), ); await tester.pumpAndSettle(); expect(find.textContaining('OpenStreetMap'), findsOneWidget); expect(find.textContaining('Radar-DPC'), findsNothing); }); testWidgets('says when no base map is configured', (tester) async { await tester.pumpWidget( wrap( Scaffold( body: AttributionBar( region: region, activeSourceIds: const {}, showBaseMapNotice: true, ), ), region, ), ); await tester.pumpAndSettle(); expect(find.textContaining('Mappa base non configurata'), findsOneWidget); }); testWidgets('opens the Sources screen when tapped', (tester) async { await tester.pumpWidget( wrap( Scaffold( body: AttributionBar( region: region, activeSourceIds: const {'osm', 'dpc'}, ), ), region, ), ); await tester.pumpAndSettle(); await tester.tap(find.byType(AttributionBar)); await tester.pumpAndSettle(); expect(find.byType(SourcesScreen), findsOneWidget); expect(find.text('App non ufficiale'), findsOneWidget); }); }); }