승인 단계 삭제 복구 흐름 구현하고 API 정렬 문서 추가
This commit is contained in:
@@ -221,4 +221,70 @@ void main() {
|
||||
expect(result, isNull);
|
||||
expect(controller.errorMessage, isNotNull);
|
||||
});
|
||||
|
||||
test('deleteStep 성공 시 단계가 비활성화된다', () async {
|
||||
when(
|
||||
() => repository.list(
|
||||
page: any(named: 'page'),
|
||||
pageSize: any(named: 'pageSize'),
|
||||
query: any(named: 'query'),
|
||||
statusId: any(named: 'statusId'),
|
||||
approverId: any(named: 'approverId'),
|
||||
approvalId: any(named: 'approvalId'),
|
||||
),
|
||||
).thenAnswer((_) async => createResult([sampleRecord]));
|
||||
|
||||
when(() => repository.delete(any())).thenAnswer((_) async {});
|
||||
|
||||
await controller.fetch();
|
||||
|
||||
final success = await controller.deleteStep(sampleRecord.step.id!);
|
||||
|
||||
expect(success, isTrue);
|
||||
expect(controller.result?.items.first.step.isDeleted, isTrue);
|
||||
});
|
||||
|
||||
test('deleteStep 실패 시 false를 반환하고 에러를 기록한다', () async {
|
||||
when(() => repository.delete(any())).thenThrow(Exception('fail'));
|
||||
|
||||
final success = await controller.deleteStep(999);
|
||||
|
||||
expect(success, isFalse);
|
||||
expect(controller.errorMessage, isNotNull);
|
||||
});
|
||||
|
||||
test('restoreStep 성공 시 단계가 활성화된다', () async {
|
||||
final deletedRecord = sampleRecord.copyWith(
|
||||
step: sampleRecord.step.copyWith(isDeleted: true),
|
||||
);
|
||||
|
||||
when(
|
||||
() => repository.list(
|
||||
page: any(named: 'page'),
|
||||
pageSize: any(named: 'pageSize'),
|
||||
query: any(named: 'query'),
|
||||
statusId: any(named: 'statusId'),
|
||||
approverId: any(named: 'approverId'),
|
||||
approvalId: any(named: 'approvalId'),
|
||||
),
|
||||
).thenAnswer((_) async => createResult([deletedRecord]));
|
||||
|
||||
when(() => repository.restore(any())).thenAnswer((_) async => sampleRecord);
|
||||
|
||||
await controller.fetch();
|
||||
|
||||
final restored = await controller.restoreStep(sampleRecord.step.id!);
|
||||
|
||||
expect(restored, isNotNull);
|
||||
expect(controller.result?.items.first.step.isDeleted, isFalse);
|
||||
});
|
||||
|
||||
test('restoreStep 실패 시 null을 반환하고 에러를 기록한다', () async {
|
||||
when(() => repository.restore(any())).thenThrow(Exception('fail'));
|
||||
|
||||
final restored = await controller.restoreStep(100);
|
||||
|
||||
expect(restored, isNull);
|
||||
expect(controller.errorMessage, isNotNull);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ 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/core/permissions/permission_manager.dart';
|
||||
import 'package:superport_v2/features/approvals/domain/entities/approval.dart';
|
||||
import 'package:superport_v2/features/approvals/step/domain/entities/approval_step_input.dart';
|
||||
import 'package:superport_v2/features/approvals/step/domain/entities/approval_step_record.dart';
|
||||
@@ -16,13 +17,19 @@ class _MockApprovalStepRepository extends Mock
|
||||
implements ApprovalStepRepository {}
|
||||
|
||||
Widget _buildApp(Widget child) {
|
||||
final manager = PermissionManager(
|
||||
overrides: {'/approvals/steps': PermissionAction.values.toSet()},
|
||||
);
|
||||
return MaterialApp(
|
||||
home: ShadTheme(
|
||||
data: ShadThemeData(
|
||||
colorScheme: const ShadSlateColorScheme.light(),
|
||||
brightness: Brightness.light,
|
||||
home: PermissionScope(
|
||||
manager: manager,
|
||||
child: ShadTheme(
|
||||
data: ShadThemeData(
|
||||
colorScheme: const ShadSlateColorScheme.light(),
|
||||
brightness: Brightness.light,
|
||||
),
|
||||
child: Scaffold(body: child),
|
||||
),
|
||||
child: Scaffold(body: child),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -263,4 +270,92 @@ void main() {
|
||||
findsOneWidget,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('삭제 버튼 확인 후 저장소 삭제를 호출한다', (tester) async {
|
||||
dotenv.testLoad(fileInput: 'FEATURE_APPROVALS_ENABLED=true\n');
|
||||
repository = _MockApprovalStepRepository();
|
||||
GetIt.I.registerLazySingleton<ApprovalStepRepository>(() => repository);
|
||||
|
||||
when(
|
||||
() => repository.list(
|
||||
page: any(named: 'page'),
|
||||
pageSize: any(named: 'pageSize'),
|
||||
query: any(named: 'query'),
|
||||
statusId: any(named: 'statusId'),
|
||||
approverId: any(named: 'approverId'),
|
||||
approvalId: any(named: 'approvalId'),
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => PaginatedResult<ApprovalStepRecord>(
|
||||
items: [record],
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 1,
|
||||
),
|
||||
);
|
||||
|
||||
when(() => repository.delete(any())).thenAnswer((_) async {});
|
||||
|
||||
await tester.pumpWidget(_buildApp(const ApprovalStepPage()));
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final deleteFinder = find.byKey(const ValueKey('step_delete_501_1'));
|
||||
final deleteButton = tester.widget<ShadButton>(deleteFinder);
|
||||
deleteButton.onPressed?.call();
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.widgetWithText(ShadButton, '삭제').last);
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
verify(() => repository.delete(501)).called(1);
|
||||
});
|
||||
|
||||
testWidgets('복구 버튼 확인 후 저장소 복구를 호출한다', (tester) async {
|
||||
dotenv.testLoad(fileInput: 'FEATURE_APPROVALS_ENABLED=true\n');
|
||||
repository = _MockApprovalStepRepository();
|
||||
GetIt.I.registerLazySingleton<ApprovalStepRepository>(() => repository);
|
||||
|
||||
final deletedRecord = record.copyWith(
|
||||
step: record.step.copyWith(isDeleted: true),
|
||||
);
|
||||
|
||||
when(
|
||||
() => repository.list(
|
||||
page: any(named: 'page'),
|
||||
pageSize: any(named: 'pageSize'),
|
||||
query: any(named: 'query'),
|
||||
statusId: any(named: 'statusId'),
|
||||
approverId: any(named: 'approverId'),
|
||||
approvalId: any(named: 'approvalId'),
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => PaginatedResult<ApprovalStepRecord>(
|
||||
items: [deletedRecord],
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
total: 1,
|
||||
),
|
||||
);
|
||||
|
||||
when(() => repository.restore(any())).thenAnswer((_) async => record);
|
||||
|
||||
await tester.pumpWidget(_buildApp(const ApprovalStepPage()));
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final restoreFinder = find.byKey(const ValueKey('step_restore_501_1'));
|
||||
final restoreButton = tester.widget<ShadButton>(restoreFinder);
|
||||
restoreButton.onPressed?.call();
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.widgetWithText(ShadButton, '복구').last);
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
verify(() => repository.restore(501)).called(1);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user