JJ_MKVMaker/test/secret_field_contract_test....

83 lines
3.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:jj_mkvmaker/ui/secret_field.dart';
/// W 공용 위젯 약속 (SecretField): 처음은 늘 가림 · 눈 단추는 눌러 켜고 끄기 (누르는 동안만이 아님) · 자동 고침 · 추천 끔 ·
/// 바깥 가리기 하나로 칸 여럿 · 좁은 폭 · 큰 글자에서 넘치지 않음. 위젯 하나에 대해 한 번만 둔다 (설계 7-2)
void main() {
TextField field(WidgetTester t, int i) => t.widget<TextField>(find.byType(TextField).at(i));
EditableText edit(WidgetTester t, int i) => t.widget<EditableText>(find.byType(EditableText).at(i));
Future<void> show(WidgetTester t, Widget child, {double width = 412, double scale = 1}) async {
t.view.physicalSize = Size(width, 900);
t.view.devicePixelRatio = 1;
addTearDown(t.view.reset);
await t.pumpWidget(MaterialApp(
home: MediaQuery(
data: MediaQueryData(size: Size(width, 900), textScaler: TextScaler.linear(scale)),
child: Scaffold(body: Column(children: [child])),
),
));
}
testWidgets('스스로 들기: 처음 가림 → 누르면 보임 (손을 떼도 그대로) → 다시 누르면 가림', (t) async {
final c = TextEditingController(text: 'pw');
await show(t, SecretField(controller: c, label: '비밀번호'));
expect(field(t, 0).obscureText, isTrue);
expect(field(t, 0).autocorrect, isFalse);
expect(field(t, 0).enableSuggestions, isFalse);
expect(find.byTooltip('보이기'), findsOneWidget);
expect(find.byIcon(Icons.visibility_outlined), findsOneWidget);
await t.tap(find.byType(IconButton));
await t.pump();
expect(field(t, 0).obscureText, isFalse, reason: '누른 뒤 손을 떼도 보임');
expect(find.byTooltip('가리기'), findsOneWidget);
expect(find.byIcon(Icons.visibility_off_outlined), findsOneWidget);
await t.tap(find.byType(IconButton));
await t.pump();
expect(field(t, 0).obscureText, isTrue);
expect(edit(t, 0).controller.text, 'pw', reason: '보이기 · 가리기는 글을 바꾸지 않음');
});
testWidgets('바깥 가리기: 눈 단추 하나가 두 칸을 함께, 단추 없는 칸은 따름', (t) async {
var hidden = true;
await show(
t,
StatefulBuilder(
builder: (ctx, set) => Column(children: [
SecretField(controller: TextEditingController(), label: 'a', hidden: hidden, onToggle: () => set(() => hidden = !hidden)),
SecretField(controller: TextEditingController(), label: 'b', hidden: hidden),
]),
));
expect(find.byType(IconButton), findsOneWidget, reason: '단추는 첫 칸에만');
expect([field(t, 0).obscureText, field(t, 1).obscureText], [true, true]);
await t.tap(find.byType(IconButton));
await t.pump();
expect([field(t, 0).obscureText, field(t, 1).obscureText], [false, false]);
});
testWidgets('오류 글 · 도움 글이 칸 아래에 보임', (t) async {
await show(t, SecretField(controller: TextEditingController(), label: '다시 넣기', helper: '없으면 비웁니다', errorText: '두 비밀번호가 다릅니다'));
expect(find.text('두 비밀번호가 다릅니다'), findsOneWidget);
});
for (final width in [300.0, 412.0]) {
for (final scale in [1.0, 2.0]) {
testWidgets('폭 $width · 배율 $scale: 긴 이름 · 도움 글도 넘치지 않음', (t) async {
await show(
t,
SecretField(
controller: TextEditingController(),
label: 'API key or username:password',
helper: 'If set, encrypts with AES-256. Leave empty for a plain ZIP archive file'),
width: width,
scale: scale);
expect(t.takeException(), isNull);
expect(t.getRect(find.byType(IconButton)).right, lessThanOrEqualTo(width));
});
}
}
}