resolved issue #178(switch from GET->POST if payload exists)
This commit is contained in:
Ashita Prasad
2024-09-16 17:07:36 +05:30
committed by GitHub
12 changed files with 209 additions and 34 deletions

3
.gitignore vendored
View File

@ -57,3 +57,6 @@ coverage/*
installers/* installers/*
.metadata .metadata
.fvm/ .fvm/
# Testing Files & Folders
test-hive-storage

View File

@ -120,7 +120,7 @@ class DashApp extends ConsumerWidget {
home: showWorkspaceSelector home: showWorkspaceSelector
? WorkspaceSelector( ? WorkspaceSelector(
onContinue: (val) async { onContinue: (val) async {
await openBoxes(kIsDesktop, val); await initHiveBoxes(kIsDesktop, val);
ref ref
.read(settingsProvider.notifier) .read(settingsProvider.notifier)
.update(workspaceFolderPath: val); .update(workspaceFolderPath: val);

View File

@ -42,7 +42,7 @@ Future<bool> initApp(
try { try {
debugPrint("initializeUsingPath: $initializeUsingPath"); debugPrint("initializeUsingPath: $initializeUsingPath");
debugPrint("workspaceFolderPath: ${settingsModel?.workspaceFolderPath}"); debugPrint("workspaceFolderPath: ${settingsModel?.workspaceFolderPath}");
final openBoxesStatus = await openBoxes( final openBoxesStatus = await initHiveBoxes(
initializeUsingPath, initializeUsingPath,
settingsModel?.workspaceFolderPath, settingsModel?.workspaceFolderPath,
); );

View File

@ -17,6 +17,21 @@ class EditRequestBody extends ConsumerWidget {
final contentType = ref.watch(selectedRequestModelProvider final contentType = ref.watch(selectedRequestModelProvider
.select((value) => value?.httpRequestModel?.bodyContentType)); .select((value) => value?.httpRequestModel?.bodyContentType));
// TODO: #178 GET->POST Currently switches to POST everytime user edits body even if the user intentionally chooses GET
// final sm = ScaffoldMessenger.of(context);
// void changeToPostMethod() {
// if (requestModel?.httpRequestModel!.method == HTTPVerb.get) {
// ref
// .read(collectionStateNotifierProvider.notifier)
// .update(selectedId, method: HTTPVerb.post);
// sm.hideCurrentSnackBar();
// sm.showSnackBar(getSnackBar(
// "Switched to POST method",
// small: false,
// ));
// }
// }
return Column( return Column(
children: [ children: [
const SizedBox( const SizedBox(
@ -33,8 +48,12 @@ class EditRequestBody extends ConsumerWidget {
), ),
Expanded( Expanded(
child: switch (contentType) { child: switch (contentType) {
ContentType.formdata => ContentType.formdata => const Padding(
const Padding(padding: kPh4, child: FormDataWidget()), padding: kPh4,
child: FormDataWidget(
// TODO: See changeToPostMethod above
// changeMethodToPost: changeToPostMethod,
)),
// TODO: Fix JsonTextFieldEditor & plug it here // TODO: Fix JsonTextFieldEditor & plug it here
ContentType.json => Padding( ContentType.json => Padding(
padding: kPt5o10, padding: kPt5o10,
@ -43,6 +62,7 @@ class EditRequestBody extends ConsumerWidget {
fieldKey: "$selectedId-json-body-editor", fieldKey: "$selectedId-json-body-editor",
initialValue: requestModel?.httpRequestModel?.body, initialValue: requestModel?.httpRequestModel?.body,
onChanged: (String value) { onChanged: (String value) {
// changeToPostMethod();
ref ref
.read(collectionStateNotifierProvider.notifier) .read(collectionStateNotifierProvider.notifier)
.update(selectedId, body: value); .update(selectedId, body: value);
@ -56,6 +76,7 @@ class EditRequestBody extends ConsumerWidget {
fieldKey: "$selectedId-body-editor", fieldKey: "$selectedId-body-editor",
initialValue: requestModel?.httpRequestModel?.body, initialValue: requestModel?.httpRequestModel?.body,
onChanged: (String value) { onChanged: (String value) {
// changeToPostMethod();
ref ref
.read(collectionStateNotifierProvider.notifier) .read(collectionStateNotifierProvider.notifier)
.update(selectedId, body: value); .update(selectedId, body: value);

View File

@ -1,3 +1,4 @@
import 'package:flutter/foundation.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_flutter/hive_flutter.dart';
const String kDataBox = "apidash-data"; const String kDataBox = "apidash-data";
@ -10,7 +11,7 @@ const String kHistoryMetaBox = "apidash-history-meta";
const String kHistoryBoxIds = "historyIds"; const String kHistoryBoxIds = "historyIds";
const String kHistoryLazyBox = "apidash-history-lazy"; const String kHistoryLazyBox = "apidash-history-lazy";
Future<bool> openBoxes( Future<bool> initHiveBoxes(
bool initializeUsingPath, bool initializeUsingPath,
String? workspaceFolderPath, String? workspaceFolderPath,
) async { ) async {
@ -24,17 +25,65 @@ Future<bool> openBoxes(
} else { } else {
await Hive.initFlutter(); await Hive.initFlutter();
} }
final openHiveBoxesStatus = await openHiveBoxes();
return openHiveBoxesStatus;
} catch (e) {
return false;
}
}
Future<bool> openHiveBoxes() async {
try {
await Hive.openBox(kDataBox); await Hive.openBox(kDataBox);
await Hive.openBox(kEnvironmentBox); await Hive.openBox(kEnvironmentBox);
await Hive.openBox(kHistoryMetaBox); await Hive.openBox(kHistoryMetaBox);
await Hive.openLazyBox(kHistoryLazyBox); await Hive.openLazyBox(kHistoryLazyBox);
return true; return true;
} catch (e) { } catch (e) {
debugPrint("ERROR OPEN HIVE BOXES: $e");
return false; return false;
} }
} }
Future<void> clearHiveBoxes() async {
try {
if (Hive.isBoxOpen(kDataBox)) {
await Hive.box(kDataBox).clear();
}
if (Hive.isBoxOpen(kEnvironmentBox)) {
await Hive.box(kEnvironmentBox).clear();
}
if (Hive.isBoxOpen(kHistoryMetaBox)) {
await Hive.box(kHistoryMetaBox).clear();
}
if (Hive.isBoxOpen(kHistoryLazyBox)) {
await Hive.lazyBox(kHistoryLazyBox).clear();
}
} catch (e) {
debugPrint("ERROR CLEAR HIVE BOXES: $e");
}
}
Future<void> deleteHiveBoxes() async {
try {
if (Hive.isBoxOpen(kDataBox)) {
await Hive.box(kDataBox).deleteFromDisk();
}
if (Hive.isBoxOpen(kEnvironmentBox)) {
await Hive.box(kEnvironmentBox).deleteFromDisk();
}
if (Hive.isBoxOpen(kHistoryMetaBox)) {
await Hive.box(kHistoryMetaBox).deleteFromDisk();
}
if (Hive.isBoxOpen(kHistoryLazyBox)) {
await Hive.lazyBox(kHistoryLazyBox).deleteFromDisk();
}
await Hive.close();
} catch (e) {
debugPrint("ERROR DELETE HIVE BOXES: $e");
}
}
final hiveHandler = HiveHandler(); final hiveHandler = HiveHandler();
class HiveHandler { class HiveHandler {
@ -93,6 +142,8 @@ class HiveHandler {
Future clear() async { Future clear() async {
await dataBox.clear(); await dataBox.clear();
await environmentBox.clear(); await environmentBox.clear();
await historyMetaBox.clear();
await historyLazyBox.clear();
} }
Future<void> removeUnused() async { Future<void> removeUnused() async {

View File

@ -259,10 +259,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: dart_style name: dart_style
sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.6" version: "2.3.7"
dartx: dartx:
dependency: transitive dependency: transitive
description: description:
@ -596,10 +596,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: fvp name: fvp
sha256: "6462fd078de4478a0990d437463897036cff98aff3f0ac9efbbf817c99654c87" sha256: "040aa12beccd5bc60631259f27a481c4abc11a389aa4f57a47b643f58fe0b060"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.24.1" version: "0.26.1"
glob: glob:
dependency: transitive dependency: transitive
description: description:
@ -778,10 +778,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: just_audio name: just_audio
sha256: ee50602364ba83fa6308f5512dd560c713ec3e1f2bc75f0db43618f0d82ef71a sha256: d8e8aaf417d33e345299c17f6457f72bd4ba0c549dc34607abb5183a354edc4d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.9.39" version: "0.9.40"
just_audio_mpv: just_audio_mpv:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1552,10 +1552,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: uuid name: uuid
sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90" sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.4.2" version: "4.5.0"
vector_graphics: vector_graphics:
dependency: transitive dependency: transitive
description: description:
@ -1727,4 +1727,4 @@ packages:
version: "3.1.2" version: "3.1.2"
sdks: sdks:
dart: ">=3.5.0-259.0.dev <3.999.0" dart: ">=3.5.0-259.0.dev <3.999.0"
flutter: ">=3.22.0" flutter: ">=3.24.3"

View File

@ -5,7 +5,7 @@ version: 0.4.0+4
environment: environment:
sdk: ">=3.0.0 <4.0.0" sdk: ">=3.0.0 <4.0.0"
flutter: ">=3.19.0" flutter: ">=3.24.3"
dependencies: dependencies:
flutter: flutter:
@ -18,7 +18,7 @@ dependencies:
url: https://github.com/foss42/curl_converter.git url: https://github.com/foss42/curl_converter.git
ref: 726e8cd04aeb326211af27f75920be5b21c90bb4 ref: 726e8cd04aeb326211af27f75920be5b21c90bb4
data_table_2: ^2.5.15 data_table_2: ^2.5.15
dart_style: ^2.3.6 dart_style: ^2.3.7
desktop_drop: ^0.4.4 desktop_drop: ^0.4.4
extended_text_field: ^16.0.0 extended_text_field: ^16.0.0
file_selector: ^1.0.3 file_selector: ^1.0.3
@ -30,7 +30,7 @@ dependencies:
flutter_svg: ^2.0.10+1 flutter_svg: ^2.0.10+1
flutter_typeahead: ^5.2.0 flutter_typeahead: ^5.2.0
freezed_annotation: ^2.4.1 freezed_annotation: ^2.4.1
fvp: ^0.24.1 fvp: ^0.26.1
google_fonts: ^6.2.1 google_fonts: ^6.2.1
highlighter: ^0.1.1 highlighter: ^0.1.1
hive_flutter: ^1.1.0 hive_flutter: ^1.1.0
@ -45,7 +45,7 @@ dependencies:
url: https://github.com/foss42/json_data_explorer.git url: https://github.com/foss42/json_data_explorer.git
ref: b7dde2f85dff4f482eed7eda4ef2a71344ef8b3a ref: b7dde2f85dff4f482eed7eda4ef2a71344ef8b3a
json_text_field: ^1.2.0 json_text_field: ^1.2.0
just_audio: ^0.9.34 just_audio: ^0.9.40
just_audio_mpv: ^0.1.7 just_audio_mpv: ^0.1.7
just_audio_windows: ^0.2.0 just_audio_windows: ^0.2.0
lottie: ^3.1.0 lottie: ^3.1.0
@ -65,7 +65,7 @@ dependencies:
scrollable_positioned_list: ^0.3.8 scrollable_positioned_list: ^0.3.8
shared_preferences: ^2.3.2 shared_preferences: ^2.3.2
url_launcher: ^6.2.5 url_launcher: ^6.2.5
uuid: ^4.3.3 uuid: ^4.5.0
vector_graphics_compiler: ^1.1.9+1 vector_graphics_compiler: ^1.1.9+1
video_player: ^2.8.7 video_player: ^2.8.7
video_player_platform_interface: ^6.2.2 video_player_platform_interface: ^6.2.2

View File

@ -0,0 +1,54 @@
import 'package:apidash/consts.dart';
import 'package:apidash/screens/home_page/editor_pane/details_card/request_pane/request_body.dart';
import 'package:apidash/widgets/editor.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:apidash/providers/providers.dart';
import 'helpers.dart';
void main() async {
TestWidgetsFlutterBinding.ensureInitialized();
setUp(() async {
await testSetUpTempDirForHive();
});
testWidgets(
'Request method changes from GET to POST when body is added and Snackbar is shown',
(WidgetTester tester) async {
// Set up the test environment
final container = createContainer();
final notifier = container.read(collectionStateNotifierProvider.notifier);
// Ensure the initial request is a GET request with no body
final id = notifier.state!.entries.first.key;
expect(
notifier.getRequestModel(id)!.httpRequestModel!.method, HTTPVerb.get);
expect(notifier.getRequestModel(id)!.httpRequestModel!.body, isNull);
// Build the EditRequestBody widget
await tester.pumpWidget(
ProviderScope(
// ignore: deprecated_member_use
parent: container,
child: const MaterialApp(
home: Scaffold(
body: EditRequestBody(),
),
),
),
);
// Add a body to the request, which should trigger the method change
await tester.enterText(find.byType(TextFieldEditor), 'new body added');
await tester.pump(); // Process the state change
// Verify that the request method changed to POST
expect(
notifier.getRequestModel(id)!.httpRequestModel!.method, HTTPVerb.post);
// Verify that the Snackbar is shown
expect(find.text('Switched to POST method'), findsOneWidget);
}, skip: true);
}

View File

@ -0,0 +1,57 @@
import 'dart:io';
import 'package:apidash/services/hive_services.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
/// A testing utility which creates a [ProviderContainer] and automatically
/// disposes it at the end of the test.
ProviderContainer createContainer({
ProviderContainer? parent,
List<Override> overrides = const [],
List<ProviderObserver>? observers,
}) {
// Create a ProviderContainer, and optionally allow specifying parameters.
final container = ProviderContainer(
parent: parent,
overrides: overrides,
observers: observers,
);
// When the test ends, dispose the container.
addTearDown(container.dispose);
return container;
}
Future<void> testSetUpForHive() async {
// override path_provider methodCall to point
// path to temporary location for all unit tests
const MethodChannel channel =
MethodChannel('plugins.flutter.io/path_provider');
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(channel, (MethodCall methodCall) async {
return './test-hive-storage/';
});
await initHiveBoxes(false, null);
// await deleteHiveBoxes();
// await openHiveBoxes();
}
Future<void> testSetUpTempDirForHive() async {
const MethodChannel channel =
MethodChannel('plugins.flutter.io/path_provider');
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(channel, (MethodCall methodCall) async {
if (methodCall.method == 'getApplicationDocumentsDirectory') {
// Create a mock app doc directory for testing
Directory tempDir =
await Directory.systemTemp.createTemp('mock_app_doc_dir');
return tempDir.path; // Return the path to the mock directory
}
return null;
});
await initHiveBoxes(false, null);
}

View File

@ -1,4 +1,3 @@
import 'dart:io';
//import 'package:spot/spot.dart'; //import 'package:spot/spot.dart';
import 'package:apidash/providers/providers.dart'; import 'package:apidash/providers/providers.dart';
import 'package:apidash/screens/common_widgets/common_widgets.dart'; import 'package:apidash/screens/common_widgets/common_widgets.dart';
@ -12,7 +11,6 @@ import 'package:apidash/screens/home_page/editor_pane/url_card.dart';
import 'package:apidash/screens/home_page/home_page.dart'; import 'package:apidash/screens/home_page/home_page.dart';
import 'package:apidash/screens/settings_page.dart'; import 'package:apidash/screens/settings_page.dart';
import 'package:apidash/screens/history/history_page.dart'; import 'package:apidash/screens/history/history_page.dart';
import 'package:apidash/services/hive_services.dart';
import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/widgets/widgets.dart';
import 'package:extended_text_field/extended_text_field.dart'; import 'package:extended_text_field/extended_text_field.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -22,24 +20,13 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import '../extensions/widget_tester_extensions.dart'; import '../extensions/widget_tester_extensions.dart';
import '../test_consts.dart'; import '../test_consts.dart';
import 'helpers.dart';
void main() { void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
setUp(() async { setUp(() async {
const MethodChannel channel = await testSetUpTempDirForHive();
MethodChannel('plugins.flutter.io/path_provider');
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(channel, (MethodCall methodCall) async {
if (methodCall.method == 'getApplicationDocumentsDirectory') {
// Create a mock app doc directory for testing
Directory tempDir =
await Directory.systemTemp.createTemp('mock_app_doc_dir');
return tempDir.path; // Return the path to the mock directory
}
return null;
});
await openBoxes(false, null);
final flamante = rootBundle.load('google_fonts/OpenSans-Medium.ttf'); final flamante = rootBundle.load('google_fonts/OpenSans-Medium.ttf');
final fontLoader = FontLoader('OpenSans')..addFont(flamante); final fontLoader = FontLoader('OpenSans')..addFont(flamante);
await fontLoader.load(); await fontLoader.load();

View File

@ -6,6 +6,7 @@ import 'package:apidash/models/models.dart';
import 'package:apidash/consts.dart'; import 'package:apidash/consts.dart';
void main() { void main() {
dataTableShowLogs = false;
testWidgets('Testing RequestFormDataTable', (WidgetTester tester) async { testWidgets('Testing RequestFormDataTable', (WidgetTester tester) async {
const List<FormDataModel> sampleData = [ const List<FormDataModel> sampleData = [
FormDataModel(name: 'Key1', value: 'Value1', type: FormDataType.file), FormDataModel(name: 'Key1', value: 'Value1', type: FormDataType.file),

View File

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
dataTableShowLogs = false;
testWidgets('Testing RequestDataTable', (WidgetTester tester) async { testWidgets('Testing RequestDataTable', (WidgetTester tester) async {
final Map<String, String> sampleData = { final Map<String, String> sampleData = {
'Key1': 'Value1', 'Key1': 'Value1',