JJ_MKVMaker/test/jj_title_bar_contract_test....

68 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:jj_mkvmaker/ui/jj_title_bar.dart';
import 'package:jj_mkvmaker/ui/tail_text.dart';
/// W 공용 위젯 약속 (JjTitleBar): 제목은 한 줄 (넘치면 "…", 경로는 끝이 보이게) · 좁으면 뒤 단추들을 둘째 줄로 (숨기지 않음) ·
/// 300 · 412 폭 · 글자 배율 2 에서 넘치지 않음. 위젯 하나에 대해 한 번만 둔다 (설계 7-2)
void main() {
const long = '휴지통 · 1234개 · 56.7 GB - 아주 긴 제목이 이어져 한 줄에 다 들어가지 않는 경우';
Future<void> show(WidgetTester t, PreferredSizeWidget Function(BuildContext) bar, {double width = 412, double scale = 1}) async {
t.view.physicalSize = Size(width, 800);
t.view.devicePixelRatio = 1;
addTearDown(t.view.reset);
await t.pumpWidget(MaterialApp(
home: MediaQuery(
data: MediaQueryData(size: Size(width, 800), textScaler: TextScaler.linear(scale)),
child: Builder(builder: (ctx) => Scaffold(appBar: bar(ctx), body: const SizedBox.expand())),
),
));
}
List<Widget> wide() => [
OutlinedButton.icon(onPressed: () {}, icon: const Icon(Icons.create_new_folder_outlined), label: const Text('새 폴더')),
FilledButton(onPressed: () {}, child: const Text('이 폴더 고르기')),
IconButton(tooltip: '보이기', icon: const Icon(Icons.visibility_off_outlined), onPressed: () {}),
];
for (final width in [300.0, 412.0]) {
for (final scale in [1.0, 2.0]) {
testWidgets('폭 $width · 배율 $scale: 긴 제목 한 줄 · 넘치지 않음', (t) async {
await show(t, (ctx) => jjTitleBar(ctx, title: long, actions: [IconButton(icon: const Icon(Icons.refresh), onPressed: () {})]),
width: width, scale: scale);
expect(t.takeException(), isNull);
final text = t.widget<Text>(find.text(long));
expect([text.maxLines, text.overflow], [1, TextOverflow.ellipsis]);
expect(t.getRect(find.byIcon(Icons.refresh)).right, lessThanOrEqualTo(width));
});
testWidgets('폭 $width · 배율 $scale: 넓은 단추는 좁으면 둘째 줄 - 모두 보이고 넘치지 않음', (t) async {
await show(t, (ctx) => jjTitleBar(ctx, title: long, actions: wide(), twoLinesBelow: 480), width: width, scale: scale);
expect(t.takeException(), isNull);
final title = t.getRect(find.text(long));
for (final f in [find.text('새 폴더'), find.text('이 폴더 고르기'), find.byIcon(Icons.visibility_off_outlined)]) {
expect(f, findsOneWidget);
final r = t.getRect(f);
expect(r.top, greaterThan(title.bottom), reason: '제목 아래 줄');
expect([r.left >= 0, r.right <= width], [true, true], reason: '화면 안에 다 보임');
}
});
}
}
testWidgets('넓은 화면에서는 한 줄 (둘째 줄 없음)', (t) async {
await show(t, (ctx) => jjTitleBar(ctx, title: '제목', actions: wide(), twoLinesBelow: 480), width: 960);
expect(t.takeException(), isNull);
expect((t.getRect(find.text('새 폴더')).center.dy - t.getRect(find.text('제목')).center.dy).abs(), lessThan(4));
});
testWidgets('경로 제목은 끝 (지금 폴더) 이 보임', (t) async {
const path = 'NAS / 동영상 / 2026 / 여름 휴가 / 바다에서 찍은 것';
await show(t, (ctx) => jjTitleBar(ctx, title: path, path: true), width: 300);
expect(t.takeException(), isNull);
expect(find.byType(TailText), findsOneWidget);
expect(find.textContaining('바다에서 찍은 것'), findsOneWidget);
});
}