결재 템플릿 화면 위젯 테스트 추가
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
|
||||
import 'package:superport_v2/core/common/models/paginated_result.dart';
|
||||
import 'package:superport_v2/features/approvals/domain/entities/approval_template.dart';
|
||||
import 'package:superport_v2/features/approvals/domain/repositories/approval_template_repository.dart';
|
||||
import 'package:superport_v2/features/approvals/template/presentation/pages/approval_template_page.dart';
|
||||
|
||||
class _MockApprovalTemplateRepository extends Mock
|
||||
implements ApprovalTemplateRepository {}
|
||||
|
||||
class _FakeTemplateInput extends Fake implements ApprovalTemplateInput {}
|
||||
|
||||
class _FakeTemplateStepInput extends Fake
|
||||
implements ApprovalTemplateStepInput {}
|
||||
|
||||
Widget _buildApp(Widget child) {
|
||||
return MaterialApp(
|
||||
home: ShadTheme(
|
||||
data: ShadThemeData(
|
||||
colorScheme: const ShadSlateColorScheme.light(),
|
||||
brightness: Brightness.light,
|
||||
),
|
||||
child: Scaffold(body: child),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
setUpAll(() {
|
||||
registerFallbackValue(_FakeTemplateInput());
|
||||
registerFallbackValue(_FakeTemplateStepInput());
|
||||
registerFallbackValue(<ApprovalTemplateStepInput>[]);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await GetIt.I.reset();
|
||||
dotenv.clean();
|
||||
});
|
||||
|
||||
testWidgets('플래그 Off 시 스펙 페이지를 노출한다', (tester) async {
|
||||
dotenv.testLoad(fileInput: 'FEATURE_APPROVALS_ENABLED=false\n');
|
||||
|
||||
await tester.pumpWidget(_buildApp(const ApprovalTemplatePage()));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('결재 템플릿 관리'), findsOneWidget);
|
||||
expect(find.text('반복되는 결재 단계를 템플릿으로 구성합니다.'), findsOneWidget);
|
||||
});
|
||||
|
||||
group('플래그 On', () {
|
||||
late _MockApprovalTemplateRepository repository;
|
||||
|
||||
setUp(() {
|
||||
dotenv.testLoad(fileInput: 'FEATURE_APPROVALS_ENABLED=true\n');
|
||||
repository = _MockApprovalTemplateRepository();
|
||||
GetIt.I.registerLazySingleton<ApprovalTemplateRepository>(
|
||||
() => repository,
|
||||
);
|
||||
});
|
||||
|
||||
ApprovalTemplate _template({bool isActive = true}) {
|
||||
return ApprovalTemplate(
|
||||
id: 10,
|
||||
code: 'AP_INBOUND',
|
||||
name: '입고 템플릿',
|
||||
description: '입고 2단계',
|
||||
note: '기본 템플릿',
|
||||
isActive: isActive,
|
||||
createdBy: null,
|
||||
createdAt: DateTime(2024, 4, 1, 9),
|
||||
updatedAt: DateTime(2024, 4, 2, 9),
|
||||
steps: [
|
||||
ApprovalTemplateStep(
|
||||
id: 1,
|
||||
stepOrder: 1,
|
||||
approver: ApprovalTemplateApprover(
|
||||
id: 21,
|
||||
employeeNo: 'E001',
|
||||
name: '최승인',
|
||||
),
|
||||
note: '확인',
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('목록을 조회해 테이블로 렌더링한다', (tester) async {
|
||||
when(
|
||||
() => repository.list(
|
||||
page: any(named: 'page'),
|
||||
pageSize: any(named: 'pageSize'),
|
||||
query: any(named: 'query'),
|
||||
isActive: any(named: 'isActive'),
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => PaginatedResult<ApprovalTemplate>(
|
||||
items: [_template()],
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 1,
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(_buildApp(const ApprovalTemplatePage()));
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('AP_INBOUND'), findsOneWidget);
|
||||
expect(find.text('입고 템플릿'), findsOneWidget);
|
||||
|
||||
verify(
|
||||
() =>
|
||||
repository.list(page: 1, pageSize: 20, query: null, isActive: null),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
testWidgets('생성 플로우에서 create 호출 후 목록을 새로고침한다', (tester) async {
|
||||
when(
|
||||
() => repository.list(
|
||||
page: any(named: 'page'),
|
||||
pageSize: any(named: 'pageSize'),
|
||||
query: any(named: 'query'),
|
||||
isActive: any(named: 'isActive'),
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => PaginatedResult<ApprovalTemplate>(
|
||||
items: const [],
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
),
|
||||
);
|
||||
|
||||
when(
|
||||
() => repository.create(any(), steps: any(named: 'steps')),
|
||||
).thenAnswer((_) async => _template());
|
||||
|
||||
await tester.pumpWidget(_buildApp(const ApprovalTemplatePage()));
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.text('템플릿 생성'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final dialogFieldsFinder = find.descendant(
|
||||
of: find.byType(Dialog),
|
||||
matching: find.byType(EditableText),
|
||||
skipOffstage: false,
|
||||
);
|
||||
final dialogFieldElements = dialogFieldsFinder.evaluate().toList();
|
||||
expect(dialogFieldElements.length, greaterThanOrEqualTo(4));
|
||||
|
||||
await tester.enterText(
|
||||
find.byWidget(dialogFieldElements[0].widget),
|
||||
'AP_NEW',
|
||||
);
|
||||
await tester.enterText(
|
||||
find.byWidget(dialogFieldElements[1].widget),
|
||||
'신규 템플릿',
|
||||
);
|
||||
|
||||
final stepFieldsFinder = find.descendant(
|
||||
of: find.byKey(const ValueKey('step_field_0')),
|
||||
matching: find.byType(EditableText),
|
||||
skipOffstage: false,
|
||||
);
|
||||
final stepFieldElements = stepFieldsFinder.evaluate().toList();
|
||||
expect(stepFieldElements.length, greaterThanOrEqualTo(2));
|
||||
|
||||
await tester.enterText(find.byWidget(stepFieldElements[1].widget), '33');
|
||||
|
||||
await tester.tap(find.text('생성 완료'));
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
verify(
|
||||
() => repository.create(any(), steps: any(named: 'steps')),
|
||||
).called(1);
|
||||
verify(
|
||||
() =>
|
||||
repository.list(page: 1, pageSize: 20, query: null, isActive: null),
|
||||
).called(greaterThanOrEqualTo(2));
|
||||
|
||||
expect(find.text('템플릿 "신규 템플릿"을 생성했습니다.'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('수정 플로우에서 fetchDetail 후 update를 호출한다', (tester) async {
|
||||
final activeTemplate = _template();
|
||||
|
||||
when(
|
||||
() => repository.list(
|
||||
page: any(named: 'page'),
|
||||
pageSize: any(named: 'pageSize'),
|
||||
query: any(named: 'query'),
|
||||
isActive: any(named: 'isActive'),
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => PaginatedResult<ApprovalTemplate>(
|
||||
items: [activeTemplate],
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 1,
|
||||
),
|
||||
);
|
||||
|
||||
when(
|
||||
() => repository.fetchDetail(
|
||||
any(),
|
||||
includeSteps: any(named: 'includeSteps'),
|
||||
),
|
||||
).thenAnswer((_) async => activeTemplate);
|
||||
|
||||
when(
|
||||
() => repository.update(any(), any(), steps: any(named: 'steps')),
|
||||
).thenAnswer((_) async => activeTemplate.copyWith(name: '수정된 템플릿'));
|
||||
|
||||
await tester.pumpWidget(_buildApp(const ApprovalTemplatePage()));
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('입고 템플릿'), findsOneWidget);
|
||||
verify(
|
||||
() =>
|
||||
repository.list(page: 1, pageSize: 20, query: null, isActive: null),
|
||||
).called(1);
|
||||
|
||||
await tester.dragUntilVisible(
|
||||
find.text('수정'),
|
||||
find.text('입고 템플릿'),
|
||||
const Offset(-200, 0),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.text('수정').first);
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final editDialogFields = find.descendant(
|
||||
of: find.byType(Dialog),
|
||||
matching: find.byType(EditableText),
|
||||
skipOffstage: false,
|
||||
);
|
||||
final editFieldElements = editDialogFields.evaluate().toList();
|
||||
expect(editFieldElements.length, greaterThanOrEqualTo(1));
|
||||
|
||||
await tester.enterText(
|
||||
find.byWidget(editFieldElements[0].widget),
|
||||
'수정된 템플릿',
|
||||
);
|
||||
|
||||
await tester.tap(find.text('수정 완료'));
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
verify(() => repository.fetchDetail(10, includeSteps: true)).called(1);
|
||||
verify(
|
||||
() => repository.update(10, any(), steps: any(named: 'steps')),
|
||||
).called(1);
|
||||
|
||||
expect(find.text('템플릿 "입고 템플릿"을(를) 수정했습니다.'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user