mirror of
https://github.com/foss42/apidash.git
synced 2025-12-10 15:23:19 +08:00
tests: add tests for dashbot action buttons(cv: 95.5)
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import 'package:apidash/dashbot/core/common/widgets/dashbot_action_buttons/dashbot_add_test_button.dart';
|
||||
import 'package:apidash/dashbot/core/constants/constants.dart';
|
||||
import 'package:apidash/dashbot/features/chat/models/chat_action.dart';
|
||||
import 'package:apidash/dashbot/features/chat/viewmodel/chat_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../test_consts.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
const action = ChatAction(
|
||||
action: 'add_test',
|
||||
target: 'test',
|
||||
actionType: ChatActionType.other,
|
||||
targetType: ChatActionTarget.test,
|
||||
);
|
||||
|
||||
group('DashbotAddTestButton', () {
|
||||
testWidgets('renders label and invokes applyAutoFix on press',
|
||||
(tester) async {
|
||||
late TestChatViewmodel notifier;
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) {
|
||||
notifier = TestChatViewmodel(ref);
|
||||
return notifier;
|
||||
}),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotAddTestButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Add Test'), findsOneWidget);
|
||||
expect(find.byIcon(Icons.playlist_add_check), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('Add Test'));
|
||||
await tester.pump();
|
||||
|
||||
expect(notifier.applyAutoFixCalls.single, same(action));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import 'package:apidash/dashbot/core/common/widgets/dashbot_action_buttons/dashbot_apply_curl_button.dart';
|
||||
import 'package:apidash/dashbot/core/constants/constants.dart';
|
||||
import 'package:apidash/dashbot/features/chat/models/chat_action.dart';
|
||||
import 'package:apidash/dashbot/features/chat/viewmodel/chat_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../test_consts.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('DashbotApplyCurlButton', () {
|
||||
testWidgets('uses default Apply label and triggers auto-fix',
|
||||
(tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'apply_curl',
|
||||
target: 'httpRequestModel',
|
||||
actionType: ChatActionType.applyCurl,
|
||||
targetType: ChatActionTarget.httpRequestModel,
|
||||
);
|
||||
|
||||
late TestChatViewmodel notifier;
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) {
|
||||
notifier = TestChatViewmodel(ref);
|
||||
return notifier;
|
||||
}),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotApplyCurlButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Apply'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('Apply'));
|
||||
await tester.pump();
|
||||
|
||||
expect(notifier.applyAutoFixCalls, hasLength(1));
|
||||
expect(notifier.applyAutoFixCalls.single, same(action));
|
||||
});
|
||||
|
||||
testWidgets('shows Create New Request when field=apply_to_new',
|
||||
(tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'apply_curl',
|
||||
target: 'httpRequestModel',
|
||||
field: 'apply_to_new',
|
||||
actionType: ChatActionType.applyCurl,
|
||||
targetType: ChatActionTarget.httpRequestModel,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) => TestChatViewmodel(ref)),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotApplyCurlButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Create New Request'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('uses path text when selecting operation', (tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'apply_curl',
|
||||
target: 'httpRequestModel',
|
||||
field: 'select_operation',
|
||||
path: '/users',
|
||||
actionType: ChatActionType.applyCurl,
|
||||
targetType: ChatActionTarget.httpRequestModel,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) => TestChatViewmodel(ref)),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotApplyCurlButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('/users'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
import 'package:apidash/dashbot/core/common/widgets/dashbot_action_buttons/dashbot_apply_openapi_button.dart';
|
||||
import 'package:apidash/dashbot/core/constants/constants.dart';
|
||||
import 'package:apidash/dashbot/features/chat/models/chat_action.dart';
|
||||
import 'package:apidash/dashbot/features/chat/viewmodel/chat_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../test_consts.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('DashbotApplyOpenApiButton', () {
|
||||
testWidgets('defaults to Apply label and invokes auto fix', (tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'apply_openapi',
|
||||
target: 'httpRequestModel',
|
||||
actionType: ChatActionType.applyOpenApi,
|
||||
targetType: ChatActionTarget.httpRequestModel,
|
||||
);
|
||||
|
||||
late TestChatViewmodel notifier;
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) {
|
||||
notifier = TestChatViewmodel(ref);
|
||||
return notifier;
|
||||
}),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotApplyOpenApiButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Apply'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('Apply'));
|
||||
await tester.pump();
|
||||
|
||||
expect(notifier.applyAutoFixCalls.single, same(action));
|
||||
});
|
||||
|
||||
testWidgets('shows Create New Request label when requested',
|
||||
(tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'apply_openapi',
|
||||
target: 'httpRequestModel',
|
||||
field: 'apply_to_new',
|
||||
actionType: ChatActionType.applyOpenApi,
|
||||
targetType: ChatActionTarget.httpRequestModel,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) => TestChatViewmodel(ref)),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotApplyOpenApiButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Create New Request'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('shows Apply to Selected label when field=apply_to_selected',
|
||||
(tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'apply_openapi',
|
||||
target: 'httpRequestModel',
|
||||
field: 'apply_to_selected',
|
||||
actionType: ChatActionType.applyOpenApi,
|
||||
targetType: ChatActionTarget.httpRequestModel,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) => TestChatViewmodel(ref)),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotApplyOpenApiButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Apply to Selected'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import 'package:apidash/dashbot/core/common/widgets/dashbot_action_buttons/dashbot_auto_fix_button.dart';
|
||||
import 'package:apidash/dashbot/core/constants/constants.dart';
|
||||
import 'package:apidash/dashbot/features/chat/models/chat_action.dart';
|
||||
import 'package:apidash/dashbot/features/chat/viewmodel/chat_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../test_consts.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
const action = ChatAction(
|
||||
action: 'update_field',
|
||||
target: 'httpRequestModel',
|
||||
field: 'url',
|
||||
value: 'https://api.apidash.dev/users',
|
||||
actionType: ChatActionType.updateField,
|
||||
targetType: ChatActionTarget.httpRequestModel,
|
||||
);
|
||||
|
||||
group('DashbotAutoFixButton', () {
|
||||
testWidgets('renders icon, label and triggers auto-fix', (tester) async {
|
||||
late TestChatViewmodel notifier;
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) {
|
||||
notifier = TestChatViewmodel(ref);
|
||||
return notifier;
|
||||
}),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotAutoFixButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Auto Fix'), findsOneWidget);
|
||||
expect(find.byIcon(Icons.auto_fix_high), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('Auto Fix'));
|
||||
await tester.pump();
|
||||
|
||||
expect(notifier.applyAutoFixCalls, hasLength(1));
|
||||
expect(notifier.applyAutoFixCalls.single, same(action));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:apidash/dashbot/core/common/widgets/dashbot_action_buttons/dashbot_download_doc_button.dart';
|
||||
import 'package:apidash/dashbot/core/constants/constants.dart';
|
||||
import 'package:apidash/dashbot/features/chat/models/chat_action.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../test_consts.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
late Directory tempDownloadsDir;
|
||||
|
||||
setUp(() {
|
||||
tempDownloadsDir = Directory.systemTemp.createTempSync('dashbot_download');
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
if (tempDownloadsDir.existsSync()) {
|
||||
tempDownloadsDir.deleteSync(recursive: true);
|
||||
}
|
||||
});
|
||||
|
||||
group('DashbotDownloadDocButton', () {
|
||||
testWidgets('disables download when content is empty', (tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'download_doc',
|
||||
target: 'code',
|
||||
path: 'doc',
|
||||
value: '',
|
||||
actionType: ChatActionType.downloadDoc,
|
||||
targetType: ChatActionTarget.code,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotDownloadDocButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final buttonFinder =
|
||||
find.byWidgetPredicate((widget) => widget is ButtonStyleButton);
|
||||
final button = tester.widget<ButtonStyleButton>(buttonFinder);
|
||||
expect(button.onPressed, isNull);
|
||||
});
|
||||
|
||||
// testWidgets('saves documentation to downloads directory', (tester) async {
|
||||
// const action = ChatAction(
|
||||
// action: 'download_doc',
|
||||
// target: 'code',
|
||||
// path: 'api-docs',
|
||||
// value: '# Markdown',
|
||||
// actionType: ChatActionType.downloadDoc,
|
||||
// targetType: ChatActionTarget.code,
|
||||
// );
|
||||
|
||||
// await tester.pumpWidget(
|
||||
// ProviderScope(
|
||||
// child: MaterialApp(
|
||||
// theme: kThemeDataLight,
|
||||
// home: const Scaffold(
|
||||
// body: DashbotDownloadDocButton(action: action),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
|
||||
// final buttonFinder =
|
||||
// find.byWidgetPredicate((widget) => widget is ButtonStyleButton);
|
||||
// final button = tester.widget<ButtonStyleButton>(buttonFinder);
|
||||
// expect(button.onPressed, isNotNull);
|
||||
|
||||
// await tester.tap(find.text('Download Documentation'));
|
||||
// await tester.pumpAndSettle();
|
||||
|
||||
// final savedPath =
|
||||
// '${tempDownloadsDir.path}${Platform.pathSeparator}api-docs.md';
|
||||
// final savedFile = File(savedPath);
|
||||
// expect(savedFile.existsSync(), isTrue);
|
||||
// expect(savedFile.readAsStringSync(), '# Markdown');
|
||||
// });
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import 'package:apidash/dashbot/core/common/widgets/dashbot_action_buttons/dashbot_generate_codeblock.dart';
|
||||
import 'package:apidash/dashbot/core/constants/constants.dart';
|
||||
import 'package:apidash/dashbot/features/chat/models/chat_action.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../test_consts.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('DashbotGeneratedCodeBlock', () {
|
||||
testWidgets('shows provided code value', (tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'other',
|
||||
target: 'code',
|
||||
value: 'print("hello")',
|
||||
actionType: ChatActionType.other,
|
||||
targetType: ChatActionTarget.code,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotGeneratedCodeBlock(action: action),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('print("hello")'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('falls back to placeholder when value missing', (tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'other',
|
||||
target: 'code',
|
||||
actionType: ChatActionType.other,
|
||||
targetType: ChatActionTarget.code,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotGeneratedCodeBlock(action: action),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('// No code returned'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
import 'package:apidash/dashbot/core/common/widgets/dashbot_action_buttons/dashbot_generate_language_picker_button.dart';
|
||||
import 'package:apidash/dashbot/core/constants/constants.dart';
|
||||
import 'package:apidash/dashbot/features/chat/models/chat_action.dart';
|
||||
import 'package:apidash/dashbot/features/chat/viewmodel/chat_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../test_consts.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('DashbotGenerateLanguagePicker', () {
|
||||
testWidgets('renders provided language options and sends message on tap',
|
||||
(tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'show_languages',
|
||||
target: 'codegen',
|
||||
value: ['Python (requests)', 'cURL'],
|
||||
actionType: ChatActionType.showLanguages,
|
||||
targetType: ChatActionTarget.codegen,
|
||||
);
|
||||
|
||||
late TestChatViewmodel notifier;
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) {
|
||||
notifier = TestChatViewmodel(ref);
|
||||
return notifier;
|
||||
}),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotGenerateLanguagePicker(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Python (requests)'), findsOneWidget);
|
||||
expect(find.text('cURL'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('Python (requests)'));
|
||||
await tester.pump();
|
||||
|
||||
expect(notifier.sendMessageCalls, hasLength(1));
|
||||
final call = notifier.sendMessageCalls.single;
|
||||
expect(call.text, 'Please generate code in Python (requests)');
|
||||
expect(call.type, ChatMessageType.generateCode);
|
||||
expect(call.countAsUser, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('falls back to default language list', (tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'show_languages',
|
||||
target: 'codegen',
|
||||
value: 'unexpected',
|
||||
actionType: ChatActionType.showLanguages,
|
||||
targetType: ChatActionTarget.codegen,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) => TestChatViewmodel(ref)),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotGenerateLanguagePicker(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('JavaScript (fetch)'), findsOneWidget);
|
||||
expect(find.text('Python (requests)'), findsOneWidget);
|
||||
expect(find.text('Dart (http)'), findsOneWidget);
|
||||
expect(find.text('Go (net/http)'), findsOneWidget);
|
||||
expect(find.text('cURL'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:apidash/dashbot/core/common/widgets/dashbot_action_buttons/dashbot_import_now_button.dart';
|
||||
import 'package:apidash/dashbot/core/constants/constants.dart';
|
||||
import 'package:apidash/dashbot/core/providers/dashbot_window_notifier.dart';
|
||||
import 'package:apidash/dashbot/features/chat/models/chat_action.dart';
|
||||
import 'package:apidash/dashbot/features/chat/viewmodel/chat_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../test_consts.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
const specJson = '''
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {"title": "Sample API", "version": "1.0.0"},
|
||||
"servers": [{"url": "https://api.apidash.dev"}],
|
||||
"paths": {
|
||||
"/users": {
|
||||
"get": {
|
||||
"responses": {"200": {"description": "OK"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
group('DashbotImportNowButton', () {
|
||||
testWidgets('hides dashbot window, shows picker, applies selected ops',
|
||||
(tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'import_now_openapi',
|
||||
target: 'httpRequestModel',
|
||||
value: {'sourceName': 'Sample', 'content': specJson},
|
||||
actionType: ChatActionType.other,
|
||||
targetType: ChatActionTarget.httpRequestModel,
|
||||
);
|
||||
|
||||
late TestChatViewmodel notifier;
|
||||
late RecordingDashbotWindowNotifier windowNotifier;
|
||||
final binding = TestWidgetsFlutterBinding.ensureInitialized();
|
||||
binding.window.physicalSizeTestValue = const Size(1600, 1200);
|
||||
binding.window.devicePixelRatioTestValue = 1.0;
|
||||
addTearDown(() {
|
||||
binding.window.clearPhysicalSizeTestValue();
|
||||
binding.window.clearDevicePixelRatioTestValue();
|
||||
});
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) {
|
||||
notifier = TestChatViewmodel(ref);
|
||||
return notifier;
|
||||
}),
|
||||
dashbotWindowNotifierProvider.overrideWith((ref) {
|
||||
windowNotifier = RecordingDashbotWindowNotifier();
|
||||
return windowNotifier;
|
||||
}),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotImportNowButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tap(find.text('Import Now'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Dialog should be shown; tap Import to accept default selection
|
||||
final importFinder = find.text('Import');
|
||||
expect(importFinder, findsOneWidget);
|
||||
await tester.tap(importFinder);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(windowNotifier.hideCalls, greaterThanOrEqualTo(1));
|
||||
expect(windowNotifier.showCalls, greaterThanOrEqualTo(1));
|
||||
|
||||
expect(notifier.applyAutoFixCalls, isNotEmpty);
|
||||
final applied = notifier.applyAutoFixCalls.single;
|
||||
expect(applied.action, 'apply_openapi');
|
||||
expect(applied.field, 'apply_to_new');
|
||||
expect(applied.value, isA<Map<String, dynamic>>());
|
||||
final value = applied.value as Map<String, dynamic>;
|
||||
expect(value['url'], 'https://api.apidash.dev/users');
|
||||
expect(value['method'], 'GET');
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import 'package:apidash/dashbot/core/common/widgets/dashbot_action_buttons/dsahbot_select_operation_button.dart';
|
||||
import 'package:apidash/dashbot/core/constants/constants.dart';
|
||||
import 'package:apidash/dashbot/features/chat/models/chat_action.dart';
|
||||
import 'package:apidash/dashbot/features/chat/viewmodel/chat_viewmodel.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../../test_consts.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('DashbotSelectOperationButton', () {
|
||||
testWidgets('renders operation label and applies auto fix', (tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'select_operation',
|
||||
target: 'httpRequestModel',
|
||||
field: 'select_operation',
|
||||
path: 'GET /users',
|
||||
actionType: ChatActionType.applyOpenApi,
|
||||
targetType: ChatActionTarget.httpRequestModel,
|
||||
);
|
||||
|
||||
late TestChatViewmodel notifier;
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) {
|
||||
notifier = TestChatViewmodel(ref);
|
||||
return notifier;
|
||||
}),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotSelectOperationButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('GET /users'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('GET /users'));
|
||||
await tester.pump();
|
||||
|
||||
expect(notifier.applyAutoFixCalls.single, same(action));
|
||||
});
|
||||
|
||||
testWidgets('falls back to Unknown label when path missing',
|
||||
(tester) async {
|
||||
const action = ChatAction(
|
||||
action: 'select_operation',
|
||||
target: 'httpRequestModel',
|
||||
field: 'select_operation',
|
||||
actionType: ChatActionType.applyOpenApi,
|
||||
targetType: ChatActionTarget.httpRequestModel,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) => TestChatViewmodel(ref)),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotSelectOperationButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Unknown'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:file_selector_platform_interface/file_selector_platform_interface.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:apidash/dashbot/core/common/widgets/dashbot_action_buttons/dashbot_upload_requests_button.dart';
|
||||
import 'package:apidash/dashbot/core/constants/constants.dart';
|
||||
import 'package:apidash/dashbot/features/chat/models/chat_action.dart';
|
||||
import 'package:apidash/dashbot/features/chat/viewmodel/chat_viewmodel.dart';
|
||||
|
||||
import '../../../test_consts.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
class FakeFileSelectorPlatform extends FileSelectorPlatform {
|
||||
FakeFileSelectorPlatform({this.fileToReturn});
|
||||
|
||||
XFile? fileToReturn;
|
||||
List<XTypeGroup>? lastAcceptedTypeGroups;
|
||||
|
||||
@override
|
||||
Future<XFile?> openFile({
|
||||
List<XTypeGroup>? acceptedTypeGroups,
|
||||
String? initialDirectory,
|
||||
String? confirmButtonText,
|
||||
}) async {
|
||||
lastAcceptedTypeGroups = acceptedTypeGroups;
|
||||
return fileToReturn;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<XFile>> openFiles({
|
||||
List<XTypeGroup>? acceptedTypeGroups,
|
||||
String? initialDirectory,
|
||||
String? confirmButtonText,
|
||||
}) async {
|
||||
lastAcceptedTypeGroups = acceptedTypeGroups;
|
||||
return fileToReturn == null ? <XFile>[] : <XFile>[fileToReturn!];
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> getDirectoryPath({
|
||||
String? initialDirectory,
|
||||
String? confirmButtonText,
|
||||
}) async =>
|
||||
null;
|
||||
|
||||
@override
|
||||
Future<List<String>> getDirectoryPaths({
|
||||
String? initialDirectory,
|
||||
String? confirmButtonText,
|
||||
}) async =>
|
||||
<String>[];
|
||||
|
||||
@override
|
||||
Future<String?> getSavePath({
|
||||
List<XTypeGroup>? acceptedTypeGroups,
|
||||
String? initialDirectory,
|
||||
String? suggestedName,
|
||||
String? confirmButtonText,
|
||||
}) async =>
|
||||
null;
|
||||
|
||||
@override
|
||||
Future<FileSaveLocation?> getSaveLocation({
|
||||
List<XTypeGroup>? acceptedTypeGroups,
|
||||
SaveDialogOptions options = const SaveDialogOptions(),
|
||||
}) async =>
|
||||
null;
|
||||
}
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
late FakeFileSelectorPlatform fakePlatform;
|
||||
|
||||
setUp(() {
|
||||
fakePlatform = FakeFileSelectorPlatform();
|
||||
FileSelectorPlatform.instance = fakePlatform;
|
||||
});
|
||||
|
||||
group('DashbotUploadRequestButton', () {
|
||||
testWidgets('uploads OpenAPI attachment and forwards to chat viewmodel',
|
||||
(tester) async {
|
||||
final bytes = Uint8List.fromList('openapi spec'.codeUnits);
|
||||
fakePlatform.fileToReturn = XFile.fromData(bytes,
|
||||
name: 'spec.yaml', mimeType: 'application/yaml');
|
||||
|
||||
const action = ChatAction(
|
||||
action: 'upload_asset',
|
||||
target: 'attachment',
|
||||
field: 'openapi_spec',
|
||||
value: {
|
||||
'purpose': 'OpenAPI specification',
|
||||
'accepted_types': ['application/yaml']
|
||||
},
|
||||
actionType: ChatActionType.uploadAsset,
|
||||
targetType: ChatActionTarget.attachment,
|
||||
);
|
||||
|
||||
late TestChatViewmodel notifier;
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) {
|
||||
notifier = TestChatViewmodel(ref);
|
||||
return notifier;
|
||||
}),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotUploadRequestButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tap(find.text('Upload: OpenAPI specification'));
|
||||
await tester.pump();
|
||||
|
||||
expect(fakePlatform.lastAcceptedTypeGroups, isNotNull);
|
||||
final group = fakePlatform.lastAcceptedTypeGroups!.single;
|
||||
expect(group.mimeTypes, ['application/yaml']);
|
||||
|
||||
expect(notifier.openApiAttachmentCalls, hasLength(1));
|
||||
final attachment = notifier.openApiAttachmentCalls.single;
|
||||
expect(attachment.mimeType, 'application/yaml');
|
||||
expect(attachment.sizeBytes, bytes.length);
|
||||
});
|
||||
|
||||
testWidgets('sends message for non-openapi uploads', (tester) async {
|
||||
fakePlatform.fileToReturn =
|
||||
XFile.fromData(Uint8List.fromList([1, 2, 3]), name: 'data.bin');
|
||||
|
||||
const action = ChatAction(
|
||||
action: 'upload_asset',
|
||||
target: 'attachment',
|
||||
value: {'purpose': 'Sample upload'},
|
||||
actionType: ChatActionType.uploadAsset,
|
||||
targetType: ChatActionTarget.attachment,
|
||||
);
|
||||
|
||||
late TestChatViewmodel notifier;
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) {
|
||||
notifier = TestChatViewmodel(ref);
|
||||
return notifier;
|
||||
}),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotUploadRequestButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tap(find.text('Upload: Sample upload'));
|
||||
await tester.pump();
|
||||
|
||||
expect(notifier.sendMessageCalls, hasLength(1));
|
||||
final call = notifier.sendMessageCalls.single;
|
||||
expect(call.type, ChatMessageType.general);
|
||||
expect(call.text, contains('Attached file'));
|
||||
expect(call.text, contains('size=3'));
|
||||
});
|
||||
|
||||
testWidgets('does nothing when user cancels file picker', (tester) async {
|
||||
fakePlatform.fileToReturn = null;
|
||||
|
||||
const action = ChatAction(
|
||||
action: 'upload_asset',
|
||||
target: 'attachment',
|
||||
actionType: ChatActionType.uploadAsset,
|
||||
targetType: ChatActionTarget.attachment,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
chatViewmodelProvider.overrideWith((ref) => TestChatViewmodel(ref)),
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: kThemeDataLight,
|
||||
home: Scaffold(
|
||||
body: DashbotUploadRequestButton(action: action),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tap(find.text('Upload Attachment'));
|
||||
await tester.pump();
|
||||
|
||||
// No exceptions and no attachments created
|
||||
});
|
||||
});
|
||||
}
|
||||
55
test/dashbot/widgets/action_buttons/test_utils.dart
Normal file
55
test/dashbot/widgets/action_buttons/test_utils.dart
Normal file
@@ -0,0 +1,55 @@
|
||||
import 'package:apidash/dashbot/core/model/chat_attachment.dart';
|
||||
import 'package:apidash/dashbot/core/providers/dashbot_window_notifier.dart';
|
||||
import 'package:apidash/dashbot/features/chat/models/chat_action.dart';
|
||||
import 'package:apidash/dashbot/features/chat/viewmodel/chat_viewmodel.dart';
|
||||
import 'package:apidash/dashbot/core/constants/constants.dart';
|
||||
|
||||
class TestChatViewmodel extends ChatViewmodel {
|
||||
TestChatViewmodel(super.ref);
|
||||
|
||||
final List<ChatAction> applyAutoFixCalls = [];
|
||||
final List<({String text, ChatMessageType type, bool countAsUser})>
|
||||
sendMessageCalls = [];
|
||||
final List<ChatAttachment> openApiAttachmentCalls = [];
|
||||
|
||||
bool throwOnApplyAutoFix = false;
|
||||
|
||||
@override
|
||||
Future<void> applyAutoFix(ChatAction action) async {
|
||||
applyAutoFixCalls.add(action);
|
||||
if (throwOnApplyAutoFix) {
|
||||
throw Exception('applyAutoFix error');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> sendMessage({
|
||||
required String text,
|
||||
ChatMessageType type = ChatMessageType.general,
|
||||
bool countAsUser = true,
|
||||
}) async {
|
||||
sendMessageCalls.add((text: text, type: type, countAsUser: countAsUser));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> handleOpenApiAttachment(ChatAttachment att) async {
|
||||
openApiAttachmentCalls.add(att);
|
||||
}
|
||||
}
|
||||
|
||||
class RecordingDashbotWindowNotifier extends DashbotWindowNotifier {
|
||||
int hideCalls = 0;
|
||||
int showCalls = 0;
|
||||
|
||||
@override
|
||||
void hide() {
|
||||
hideCalls += 1;
|
||||
super.hide();
|
||||
}
|
||||
|
||||
@override
|
||||
void show() {
|
||||
showCalls += 1;
|
||||
super.show();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user