Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] auto switch GET -> POST when request body is added #181

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert all changes made to this file. You can keep a local version and not commit it to the PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@opxdelwin Why did you mark this conversation as resolved. It is the reviewer's task to review the changes and mark it resolved. Also, you have still not reverted all the changes that you made to this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I apologize for marking the conversation as resolved prematurely. I wasn't aware that it's the reviewer's responsibility to mark it resolved.

Regarding the .gitignore change, I made it to prevent the auto-generated hive files during testing from cluttering the codebase. Let me know whether to still revert changes.

I understand now that I should have let the reviewers close the conversation. I'll make sure to follow the correct process next time. Thanks for bringing it to my attention.

Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@ coverage/*
installers/*
.metadata
.fvm/

# unit tests hive storage
test/unit-test-hive-storage/
9 changes: 9 additions & 0 deletions lib/providers/collection_providers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ class CollectionStateNotifier
String? message,
ResponseModel? responseModel,
}) {
// Switch from GET to POST if request has payload of any kind
// primarily, text, json and formData
if ((requestBody != null || requestFormDataList != null) &&
state![id]!.method == HTTPVerb.get) {
ref.read(autoSwitchPOSTStateProvider.notifier).state = true;
method = HTTPVerb.post;
ref.read(autoSwitchPOSTStateProvider.notifier).state = false;
}

final newModel = state![id]!.copyWith(
method: method,
url: url,
Expand Down
5 changes: 5 additions & 0 deletions lib/providers/ui_providers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ final selectedIdEditStateProvider = StateProvider<String?>((ref) => null);
final codePaneVisibleStateProvider = StateProvider<bool>((ref) => false);
final saveDataStateProvider = StateProvider<bool>((ref) => false);
final clearDataStateProvider = StateProvider<bool>((ref) => false);

/// As part of UX, when body is added to GET requests, they're
/// auto converted to POST requests. UI Snackbar trigger for the same
final autoSwitchPOSTStateProvider = StateProvider<bool>((ref) => false);

// final nameTextFieldControllerProvider =
// StateProvider.autoDispose<TextEditingController>((ref) {
// TextEditingController controller = TextEditingController(text: "");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:apidash/providers/providers.dart';
import 'package:apidash/widgets/widgets.dart';
Expand All @@ -14,7 +15,8 @@ class EditRequestPane extends ConsumerWidget {
final selectedId = ref.watch(selectedIdStateProvider);
final codePaneVisible = ref.watch(codePaneVisibleStateProvider);
final tabIndex = ref.watch(
selectedRequestModelProvider.select((value) => value?.requestTabIndex));
selectedRequestModelProvider.select((value) => value?.requestTabIndex),
);

final headerLength = ref.watch(selectedRequestModelProvider
.select((value) => value?.headersMap.length)) ??
Expand All @@ -26,6 +28,15 @@ class EditRequestPane extends ConsumerWidget {
selectedRequestModelProvider.select((value) => value?.hasBody)) ??
false;

// show snackbar when auto switch triggers
ref.listen(autoSwitchPOSTStateProvider, (_, currentValue) {
if (currentValue) {
final sm = ScaffoldMessenger.of(context);
sm.hideCurrentSnackBar();
sm.showSnackBar(getSnackBar('Switching to POST Request'));
}
});

return RequestPane(
selectedId: selectedId,
codePaneVisible: codePaneVisible,
Expand Down
28 changes: 28 additions & 0 deletions test/providers/collection_providers_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:apidash/consts.dart';
import 'package:apidash/providers/collection_providers.dart';
import 'package:flutter_test/flutter_test.dart';
import 'helpers.dart';

void main() async {
setUp(() async => await testSetUp());

test('Request method changes from GET to POST when body is added', () {
// Create a ProviderContainer for this test.
// DO NOT share ProviderContainers between tests.
final container = createContainer();
final ref = container.read(collectionStateNotifierProvider.notifier);

// One API request is preloaded always
final id = ref.state!.entries.first.key;

// preloaded API is a GET request
expect(ref.getRequestModel(id)!.method, HTTPVerb.get);
expect(ref.getRequestModel(id)!.requestBody, null);

// add request body
ref.update(id, requestBody: 'body');

// vertify new model is POST
expect(ref.getRequestModel(id)!.method, HTTPVerb.post);
});
}
39 changes: 39 additions & 0 deletions test/providers/helpers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
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> testSetUp() async {
// override path_provider methodCall to point
// path to temporary location for all unit tests
TestWidgetsFlutterBinding.ensureInitialized();
const MethodChannel channel =
MethodChannel('plugins.flutter.io/path_provider');

TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(channel, (MethodCall methodCall) async {
return './test/unit-test-hive-storage/';
});

await openBoxes();
}