mirror of
https://github.com/l5yth/potato-mesh.git
synced 2026-07-06 09:52:02 +02:00
fec649a159
* Add utility coverage tests for main.dart * Add channel names to message sorting tests * Fix MeshMessage sort test construction * chore: run dart formatter
129 lines
3.7 KiB
Dart
129 lines
3.7 KiB
Dart
// Copyright © 2025-26 l5yth & contributors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:potato_mesh_reader/main.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
test('BootstrapProgress renders stage, counts, and detail', () {
|
|
const progress = BootstrapProgress(
|
|
stage: 'Downloading',
|
|
current: 2,
|
|
total: 5,
|
|
detail: 'instances',
|
|
);
|
|
|
|
expect(progress.label, 'Downloading 2/5 • instances');
|
|
|
|
const fallback = BootstrapProgress(stage: 'Starting');
|
|
expect(fallback.label, 'Starting');
|
|
});
|
|
|
|
test('InstanceVersion summary prefers populated fields', () {
|
|
const populated = InstanceVersion(
|
|
name: 'BerlinMesh',
|
|
channel: '#MediumFast',
|
|
frequency: '868MHz',
|
|
instanceDomain: 'potatomesh.net',
|
|
);
|
|
expect(populated.summary, 'BerlinMesh · #MediumFast · 868MHz');
|
|
|
|
const minimal = InstanceVersion(
|
|
name: '',
|
|
channel: null,
|
|
frequency: null,
|
|
instanceDomain: null,
|
|
);
|
|
expect(minimal.summary, 'Unknown');
|
|
});
|
|
|
|
test('sortMessagesByRxTime keeps unknown timestamps in place', () {
|
|
MeshMessage buildMessage({
|
|
required int id,
|
|
required String text,
|
|
required String rxIso,
|
|
DateTime? rxTime,
|
|
}) {
|
|
return MeshMessage(
|
|
id: id,
|
|
rxTime: rxTime,
|
|
rxIso: rxIso,
|
|
fromId: '!$id',
|
|
nodeId: '!$id',
|
|
toId: '^',
|
|
channelName: '#general',
|
|
channel: 1,
|
|
portnum: 'TEXT',
|
|
text: text,
|
|
rssi: -50,
|
|
snr: 1.0,
|
|
hopLimit: 1,
|
|
);
|
|
}
|
|
|
|
final withTime = buildMessage(
|
|
id: 2,
|
|
rxTime: DateTime.utc(2024, 1, 1, 12, 1),
|
|
rxIso: '2024-01-01T12:01:00Z',
|
|
text: 'timed',
|
|
);
|
|
final withoutTime = buildMessage(
|
|
id: 1,
|
|
rxTime: null,
|
|
rxIso: 'unknown',
|
|
text: 'unknown',
|
|
);
|
|
final laterTime = buildMessage(
|
|
id: 3,
|
|
rxTime: DateTime.utc(2024, 1, 1, 12, 5),
|
|
rxIso: '2024-01-01T12:05:00Z',
|
|
text: 'later',
|
|
);
|
|
|
|
final sorted = sortMessagesByRxTime([withoutTime, laterTime, withTime]);
|
|
|
|
expect(sorted.first.id, withoutTime.id,
|
|
reason: 'messages without rxTime should retain position');
|
|
expect(sorted[1].id, withTime.id,
|
|
reason: 'messages with timestamps should be ordered chronologically');
|
|
expect(sorted.last.id, laterTime.id);
|
|
});
|
|
|
|
testWidgets('LoadingScreen displays progress label and icon', (tester) async {
|
|
const screen = LoadingScreen(
|
|
progress: BootstrapProgress(stage: 'Fetching'),
|
|
);
|
|
|
|
await tester.pumpWidget(const MaterialApp(home: screen));
|
|
|
|
expect(find.byType(CircularProgressIndicator), findsOneWidget);
|
|
expect(find.text('Fetching'), findsOneWidget);
|
|
expect(find.bySemanticsLabel('PotatoMesh'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('LoadingScreen surfaces errors', (tester) async {
|
|
const screen = LoadingScreen(
|
|
progress: BootstrapProgress(stage: 'Loading'),
|
|
error: 'boom',
|
|
);
|
|
|
|
await tester.pumpWidget(const MaterialApp(home: screen));
|
|
|
|
expect(find.textContaining('Failed to load: boom'), findsOneWidget);
|
|
});
|
|
}
|