From 4dad60d937022b8ae4085b3e3470dcf58b74629f Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Tue, 12 Mar 2024 01:55:28 +0100 Subject: [PATCH 001/138] Test that correct pages are displayed for navRailIndexStateProvider value --- pubspec.lock | 8 +++ pubspec.yaml | 7 +- test/providers/ui_providers_test.dart | 93 +++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 test/providers/ui_providers_test.dart diff --git a/pubspec.lock b/pubspec.lock index f48a9105..38a05b26 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -729,6 +729,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + mockito: + dependency: "direct main" + description: + name: mockito + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" + url: "https://pub.dev" + source: hosted + version: "5.4.4" mpv_dart: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8441a0f5..b4137063 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,11 +1,11 @@ name: apidash description: API Dash is a beautiful open-source cross-platform API Client built using Flutter which can help you easily create & customize your API requests, visually inspect responses and generate Dart code on the go. -publish_to: "none" +publish_to: 'none' version: 0.3.0+3 environment: - sdk: ">=3.0.0 <4.0.0" - flutter: ">=3.7.2" + sdk: '>=3.0.0 <4.0.0' + flutter: '>=3.7.2' dependencies: flutter: @@ -55,6 +55,7 @@ dependencies: dart_style: ^2.3.4 json_text_field: ^1.1.0 csv: ^5.1.1 + mockito: ^5.4.4 dev_dependencies: flutter_test: diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart new file mode 100644 index 00000000..7b32c60a --- /dev/null +++ b/test/providers/ui_providers_test.dart @@ -0,0 +1,93 @@ +import 'dart:io'; + +import 'package:apidash/providers/providers.dart'; +import 'package:apidash/screens/dashboard.dart'; +import 'package:apidash/screens/home_page/home_page.dart'; +import 'package:apidash/screens/intro_page.dart'; +import 'package:apidash/screens/settings_page.dart'; +import 'package:apidash/services/hive_services.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/mockito.dart'; + +class MockPathProviderPlatform extends Mock implements MethodChannel {} + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + setUp(() async { + const MethodChannel channel = + MethodChannel('plugins.flutter.io/path_provider'); + final MockPathProviderPlatform mock = MockPathProviderPlatform(); + 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(); + }); + + group('Testing navRailIndexStateProvider', () { + testWidgets('Dashboard should display correct initial page', + (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: Dashboard(), + ), + ), + ); + + // Verify that the HomePage is displayed initially + expect(find.byType(HomePage), findsOneWidget); + expect(find.byType(IntroPage), findsNothing); + expect(find.byType(SettingsPage), findsNothing); + }); + + testWidgets( + "Dashboard should display IntroPage when navRailIndexStateProvider is 1", + (WidgetTester tester) async { + await tester.pumpWidget( + ProviderScope( + overrides: [ + navRailIndexStateProvider.overrideWith((ref) => 1), + ], + child: const MaterialApp( + home: Dashboard(), + ), + ), + ); + + // Verify that the IntroPage is displayed + expect(find.byType(IntroPage), findsOneWidget); + expect(find.byType(HomePage), findsNothing); + expect(find.byType(SettingsPage), findsNothing); + }); + testWidgets( + "Dashboard should display SettingsPage when navRailIndexStateProvider is 2", + (WidgetTester tester) async { + await tester.pumpWidget( + ProviderScope( + overrides: [ + navRailIndexStateProvider.overrideWith((ref) => 2), + ], + child: const MaterialApp( + home: Dashboard(), + ), + ), + ); + + // Verify that the SettingsPage is displayed + expect(find.byType(SettingsPage), findsOneWidget); + expect(find.byType(IntroPage), findsNothing); + expect(find.byType(HomePage), findsNothing); + }); + }); +} From b264a7e6a4873a74ba8cf60a15b35fd60b34d52e Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Tue, 12 Mar 2024 02:13:11 +0100 Subject: [PATCH 002/138] Ensure that navigation rail index update when icon button is pressed --- test/providers/ui_providers_test.dart | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index 7b32c60a..4b632113 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -89,5 +89,26 @@ void main() { expect(find.byType(IntroPage), findsNothing); expect(find.byType(HomePage), findsNothing); }); + + testWidgets( + 'Navigation Rail index should update when icon button is pressed', + (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: Dashboard(), + ), + ), + ); + + // Tap on the Intro icon + await tester.tap(find.byIcon(Icons.help_outline)); + await tester.pump(); + + // Verify that the navRailIndexStateProvider is updated + final dashboard = tester.element(find.byType(Dashboard)); + final container = ProviderScope.containerOf(dashboard); + expect(container.read(navRailIndexStateProvider), 1); + }); }); } From ba4bd77795356a71b27138d2d2e8b30ceee17ce1 Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Tue, 12 Mar 2024 02:17:22 +0100 Subject: [PATCH 003/138] Test that nav rail index persist across widget rebuilds --- test/providers/ui_providers_test.dart | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index 4b632113..3acf30df 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -110,5 +110,40 @@ void main() { final container = ProviderScope.containerOf(dashboard); expect(container.read(navRailIndexStateProvider), 1); }); + + testWidgets('Navigation Rail index should persist across widget rebuilds', + (tester) async { + // Pump the initial widget tree + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: Dashboard(), + ), + ), + ); + + // Tap on the Settings icon to change the index to 2 + await tester.tap(find.byIcon(Icons.settings_outlined)); + await tester.pump(); // Wait for the animations to complete + + // Rebuild the widget tree with the same ProviderScope + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: Dashboard(), + ), + ), + ); + + // Verify that the navRailIndexStateProvider still has the updated value + final dashboard = tester.element(find.byType(Dashboard)); + final container = ProviderScope.containerOf(dashboard); + expect(container.read(navRailIndexStateProvider), 2); + + // Verify that the SettingsPage is still displayed after the rebuild + expect(find.byType(SettingsPage), findsOneWidget); + expect(find.byType(IntroPage), findsNothing); + expect(find.byType(HomePage), findsNothing); + }); }); } From a882d5102264b76ab8d855a495c5b0cb2290e6e3 Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Tue, 12 Mar 2024 02:38:54 +0100 Subject: [PATCH 004/138] Test that UI updates correctly when nav rail index changes --- test/providers/ui_providers_test.dart | 35 ++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index 3acf30df..3ffe1165 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -124,7 +124,7 @@ void main() { // Tap on the Settings icon to change the index to 2 await tester.tap(find.byIcon(Icons.settings_outlined)); - await tester.pump(); // Wait for the animations to complete + await tester.pump(); // Rebuild the widget tree with the same ProviderScope await tester.pumpWidget( @@ -145,5 +145,38 @@ void main() { expect(find.byType(IntroPage), findsNothing); expect(find.byType(HomePage), findsNothing); }); + + testWidgets('UI should update correctly when Navigation Rail index changes', + (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: Dashboard(), + ), + ), + ); + + // Grab the Dashboard widget and its ProviderContainer + final dashboard = tester.element(find.byType(Dashboard)); + final container = ProviderScope.containerOf(dashboard); + + // Go to IntroPage + container.read(navRailIndexStateProvider.notifier).state = 1; + await tester.pump(); + + // Verify that the IntroPage is displayed + expect(find.byType(IntroPage), findsOneWidget); + // Verify that the selected icon is the filled version (selectedIcon) + expect(find.byIcon(Icons.help), findsOneWidget); + + // Go to SettingsPage + container.read(navRailIndexStateProvider.notifier).state = 2; + await tester.pump(); + + // Verify that the SettingsPage is displayed + expect(find.byType(SettingsPage), findsOneWidget); + // Verify that the selected icon is the filled version (selectedIcon) + expect(find.byIcon(Icons.settings), findsOneWidget); + }); }); } From 405decbd565a352ff776a53b2677f07113d821df Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Tue, 12 Mar 2024 02:48:54 +0100 Subject: [PATCH 005/138] Test that navRailIndexStateProvider is properly disposed --- test/providers/ui_providers_test.dart | 41 +++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index 3ffe1165..d714998e 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -91,7 +91,7 @@ void main() { }); testWidgets( - 'Navigation Rail index should update when icon button is pressed', + 'navRailIndexStateProvider should update when icon button is pressed', (tester) async { await tester.pumpWidget( const ProviderScope( @@ -111,7 +111,8 @@ void main() { expect(container.read(navRailIndexStateProvider), 1); }); - testWidgets('Navigation Rail index should persist across widget rebuilds', + testWidgets( + 'navRailIndexStateProvider should persist across widget rebuilds', (tester) async { // Pump the initial widget tree await tester.pumpWidget( @@ -146,7 +147,8 @@ void main() { expect(find.byType(HomePage), findsNothing); }); - testWidgets('UI should update correctly when Navigation Rail index changes', + testWidgets( + 'UI should update correctly when navRailIndexStateProvider changes', (tester) async { await tester.pumpWidget( const ProviderScope( @@ -178,5 +180,38 @@ void main() { // Verify that the selected icon is the filled version (selectedIcon) expect(find.byIcon(Icons.settings), findsOneWidget); }); + + testWidgets( + 'navRailIndexStateProvider should be disposed when Dashboard is removed', + (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: Dashboard(), + ), + ), + ); + + // Grab the Dashboard widget and its ProviderContainer + final dashboard = tester.element(find.byType(Dashboard)); + final container = ProviderScope.containerOf(dashboard); + + // Pumping a different widget to remove the Dashboard from the widget tree + await tester.pumpWidget( + const MaterialApp( + home: Scaffold(body: Text('Different Widget')), + ), + ); + + // Verify that the ProviderContainer has been disposed + // by trying to read from disposed container + bool isDisposed = false; + try { + container.read(navRailIndexStateProvider); + } catch (e) { + isDisposed = true; + } + expect(isDisposed, true); + }); }); } From f71bf00dc3538a6c54bc14a7a2a37fe95e4b9a95 Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Tue, 12 Mar 2024 03:57:51 +0100 Subject: [PATCH 006/138] Remove mockito --- pubspec.lock | 8 -------- pubspec.yaml | 1 - test/providers/ui_providers_test.dart | 5 +---- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 38a05b26..f48a9105 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -729,14 +729,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" - mockito: - dependency: "direct main" - description: - name: mockito - sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" - url: "https://pub.dev" - source: hosted - version: "5.4.4" mpv_dart: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index b4137063..9135b207 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -55,7 +55,6 @@ dependencies: dart_style: ^2.3.4 json_text_field: ^1.1.0 csv: ^5.1.1 - mockito: ^5.4.4 dev_dependencies: flutter_test: diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index d714998e..f69d8ab3 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -10,9 +10,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/mockito.dart'; - -class MockPathProviderPlatform extends Mock implements MethodChannel {} void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -20,7 +17,6 @@ void main() { setUp(() async { const MethodChannel channel = MethodChannel('plugins.flutter.io/path_provider'); - final MockPathProviderPlatform mock = MockPathProviderPlatform(); TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMethodCallHandler(channel, (MethodCall methodCall) async { if (methodCall.method == 'getApplicationDocumentsDirectory') { @@ -70,6 +66,7 @@ void main() { expect(find.byType(HomePage), findsNothing); expect(find.byType(SettingsPage), findsNothing); }); + testWidgets( "Dashboard should display SettingsPage when navRailIndexStateProvider is 2", (WidgetTester tester) async { From a057281a6f69fc8ff46858b97d4a51a2dffdf250 Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Tue, 12 Mar 2024 04:07:09 +0100 Subject: [PATCH 007/138] Test that selectedIdEditStateProvider has initial value of null --- test/providers/ui_providers_test.dart | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index f69d8ab3..cc9b25c0 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/screens/dashboard.dart'; +import 'package:apidash/screens/home_page/collection_pane.dart'; import 'package:apidash/screens/home_page/home_page.dart'; import 'package:apidash/screens/intro_page.dart'; import 'package:apidash/screens/settings_page.dart'; @@ -211,4 +212,23 @@ void main() { expect(isDisposed, true); }); }); + + group("Testing selectedIdEditStateProvider", () { + testWidgets( + 'selectedIdEditStateProvider should have an initial value of null', + (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: CollectionPane(), + ), + ), + ); + + // Verify that the initial value is null + final collectionPane = tester.element(find.byType(CollectionPane)); + final container = ProviderScope.containerOf(collectionPane); + expect(container.read(selectedIdEditStateProvider), null); + }); + }); } From fa6dc8e352b5d1f806178d6bb367fc1170270afe Mon Sep 17 00:00:00 2001 From: DenserMeerkat Date: Fri, 15 Mar 2024 03:16:47 +0530 Subject: [PATCH 008/138] feat: drag scrolling --- lib/consts.dart | 8 +- .../request_pane/request_body.dart | 46 +-- .../request_pane/request_form_data.dart | 314 ++++++++++-------- .../request_pane/request_headers.dart | 212 ++++++------ .../request_pane/request_params.dart | 212 ++++++------ lib/widgets/form_data_field.dart | 2 +- lib/widgets/headerfield.dart | 1 + lib/widgets/request_widgets.dart | 1 + lib/widgets/textfields.dart | 1 + pubspec.lock | 68 ++-- pubspec.yaml | 1 + 11 files changed, 462 insertions(+), 404 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index a557023d..efde9820 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -70,6 +70,8 @@ const kP10 = EdgeInsets.all(10); const kPt24o8 = EdgeInsets.only(top: 24, left: 8.0, right: 8.0, bottom: 8.0); const kPt5o10 = EdgeInsets.only(left: 10.0, right: 10.0, top: 5.0, bottom: 10.0); +const kPh4 = EdgeInsets.symmetric(horizontal: 4); +const kPh8 = EdgeInsets.symmetric(horizontal: 8); const kPh20 = EdgeInsets.symmetric( horizontal: 20, ); @@ -113,6 +115,11 @@ const kTextButtonMinWidth = 44.0; const kRandMax = 100000; +const kDataTableScrollbarTheme = ScrollbarThemeData( + crossAxisMargin: -4, +); +const kDataTableBottomPadding = 80.0; +const kDataRowHeight = 36.0; const kTableThemeData = DaviThemeData( columnDividerThickness: 1, columnDividerColor: kColorTransparent, @@ -279,7 +286,6 @@ enum CodegenLanguage { rustUreq("Rust (ureq)", "rust", "rs"), juliaHttp("Julia (HTTP)", "julia", "jl"); - const CodegenLanguage(this.label, this.codeHighlightLang, this.ext); final String label; final String codeHighlightLang; diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart index f667f6b5..085df3f2 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_body.dart @@ -21,7 +21,6 @@ class EditRequestBody extends ConsumerWidget { decoration: BoxDecoration( color: Theme.of(context).colorScheme.background, ), - margin: kPt5o10, child: Column( children: [ const SizedBox( @@ -38,27 +37,34 @@ class EditRequestBody extends ConsumerWidget { ), Expanded( child: switch (contentType) { - ContentType.formdata => const FormDataWidget(), + ContentType.formdata => + const Padding(padding: kPh4, child: FormDataWidget()), // TODO: Fix JsonTextFieldEditor & plug it here - ContentType.json => TextFieldEditor( - key: Key("$selectedId-json-body"), - fieldKey: "$selectedId-json-body-editor", - initialValue: requestModel?.requestBody, - onChanged: (String value) { - ref - .read(collectionStateNotifierProvider.notifier) - .update(selectedId, requestBody: value); - }, + ContentType.json => Padding( + padding: kPt5o10, + child: TextFieldEditor( + key: Key("$selectedId-json-body"), + fieldKey: "$selectedId-json-body-editor", + initialValue: requestModel?.requestBody, + onChanged: (String value) { + ref + .read(collectionStateNotifierProvider.notifier) + .update(selectedId, requestBody: value); + }, + ), ), - _ => TextFieldEditor( - key: Key("$selectedId-body"), - fieldKey: "$selectedId-body-editor", - initialValue: requestModel?.requestBody, - onChanged: (String value) { - ref - .read(collectionStateNotifierProvider.notifier) - .update(selectedId, requestBody: value); - }, + _ => Padding( + padding: kPt5o10, + child: TextFieldEditor( + key: Key("$selectedId-body"), + fieldKey: "$selectedId-body-editor", + initialValue: requestModel?.requestBody, + onChanged: (String value) { + ref + .read(collectionStateNotifierProvider.notifier) + .update(selectedId, requestBody: value); + }, + ), ), }, ) diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart index 5d518e22..3b9baf9f 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart @@ -1,7 +1,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:davi/davi.dart'; +import 'package:data_table_2/data_table_2.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/models/models.dart'; @@ -31,144 +31,23 @@ class _FormDataBodyState extends ConsumerState { rows = formRows == null || formRows.isEmpty ? [kFormDataEmptyModel] : formRows; - DaviModel daviModelRows = DaviModel( - rows: rows, - columns: [ - DaviColumn( - cellPadding: kpsV5, - name: 'Key', - grow: 4, - cellBuilder: (_, row) { - int idx = row.index; - return Theme( - data: Theme.of(context), - child: FormDataField( - keyId: "$selectedId-$idx-form-v-$seed", - initialValue: rows[idx].name, - hintText: " Add Key", - onChanged: (value) { - rows[idx] = rows[idx].copyWith( - name: value, - ); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - formDataType: rows[idx].type, - onFormDataTypeChanged: (value) { - rows[idx] = rows[idx].copyWith( - type: value ?? FormDataType.text, - ); - rows[idx] = rows[idx].copyWith(value: ""); - setState(() {}); - _onFieldChange(selectedId!); - }, - ), - ); - }, - sortable: false, - ), - DaviColumn( - width: 40, - cellPadding: kpsV5, - cellAlignment: Alignment.center, - cellBuilder: (_, row) { - return Text( - "=", - style: kCodeStyle, - ); - }, - ), - DaviColumn( - name: 'Value', - grow: 4, - cellPadding: kpsV5, - cellBuilder: (_, row) { - int idx = row.index; - return rows[idx].type == FormDataType.file - ? Align( - alignment: Alignment.centerLeft, - child: Row( - children: [ - Expanded( - child: Theme( - data: Theme.of(context), - child: ElevatedButton.icon( - icon: const Icon( - Icons.snippet_folder_rounded, - size: 20, - ), - style: ButtonStyle( - shape: MaterialStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), - ), - ), - ), - onPressed: () async { - var pickedResult = await pickFile(); - if (pickedResult != null && - pickedResult.files.isNotEmpty && - pickedResult.files.first.path != null) { - rows[idx] = rows[idx].copyWith( - value: pickedResult.files.first.path!, - ); - setState(() {}); - _onFieldChange(selectedId!); - } - }, - label: Text( - (rows[idx].type == FormDataType.file && - rows[idx].value.isNotEmpty) - ? rows[idx].value.toString() - : "Select File", - textAlign: TextAlign.center, - overflow: TextOverflow.ellipsis, - style: kFormDataButtonLabelTextStyle, - ), - ), - ), - ), - ], - ), - ) - : CellField( - keyId: "$selectedId-$idx-form-v-$seed", - initialValue: rows[idx].value, - hintText: " Add Value", - onChanged: (value) { - rows[idx] = rows[idx].copyWith(value: value); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ); - }, - sortable: false, - ), - DaviColumn( - pinStatus: PinStatus.none, - width: 30, - cellBuilder: (_, row) { - return InkWell( - child: Theme.of(context).brightness == Brightness.dark - ? kIconRemoveDark - : kIconRemoveLight, - onTap: () { - seed = random.nextInt(kRandMax); - if (rows.length == 1) { - setState(() { - rows = [kFormDataEmptyModel]; - }); - } else { - rows.removeAt(row.index); - } - _onFieldChange(selectedId!); - setState(() {}); - }, - ); - }, - ), - ], - ); + List columns = const [ + DataColumn2( + label: Text('Key'), + ), + DataColumn2( + label: Text('='), + fixedWidth: 30, + ), + DataColumn2( + label: Text('Value'), + ), + DataColumn2( + label: Text('Remove'), + fixedWidth: 32, + ), + ]; + return Stack( children: [ Container( @@ -180,9 +59,160 @@ class _FormDataBodyState extends ConsumerState { child: Column( children: [ Expanded( - child: DaviTheme( - data: kTableThemeData, - child: Davi(daviModelRows), + child: Theme( + data: Theme.of(context) + .copyWith(scrollbarTheme: kDataTableScrollbarTheme), + child: DataTable2( + columnSpacing: 12, + dividerThickness: 0, + horizontalMargin: 0, + headingRowHeight: 0, + dataRowHeight: kDataRowHeight, + bottomMargin: kDataTableBottomPadding, + isVerticalScrollBarVisible: true, + columns: columns, + rows: List.generate( + rows.length, + (index) { + return DataRow( + key: ValueKey("$selectedId-$index-form-row-$seed"), + cells: [ + DataCell( + Theme( + data: Theme.of(context), + child: FormDataField( + keyId: "$selectedId-$index-form-v-$seed", + initialValue: rows[index].name, + hintText: "Add Key", + onChanged: (value) { + rows[index] = rows[index].copyWith( + name: value, + ); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + formDataType: rows[index].type, + onFormDataTypeChanged: (value) { + rows[index] = rows[index].copyWith( + type: value ?? FormDataType.text, + ); + rows[index] = + rows[index].copyWith(value: ""); + setState(() {}); + _onFieldChange(selectedId!); + }, + ), + ), + ), + DataCell( + Text( + "=", + style: kCodeStyle, + ), + ), + DataCell( + rows[index].type == FormDataType.file + ? Align( + alignment: Alignment.centerLeft, + child: Row( + children: [ + Expanded( + child: Theme( + data: Theme.of(context), + child: ElevatedButton.icon( + icon: const Icon( + Icons.snippet_folder_rounded, + size: 20, + ), + style: ButtonStyle( + shape: + MaterialStatePropertyAll( + RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 6), + ), + ), + ), + onPressed: () async { + var pickedResult = + await pickFile(); + if (pickedResult != null && + pickedResult + .files.isNotEmpty && + pickedResult.files.first + .path != + null) { + rows[index] = + rows[index].copyWith( + value: pickedResult + .files.first.path!, + ); + setState(() {}); + _onFieldChange(selectedId!); + } + }, + label: Text( + (rows[index].type == + FormDataType + .file && + rows[index] + .value + .isNotEmpty) + ? rows[index] + .value + .toString() + : "Select File", + textAlign: TextAlign.center, + overflow: + TextOverflow.ellipsis, + style: + kFormDataButtonLabelTextStyle, + ), + ), + ), + ), + ], + ), + ) + : CellField( + keyId: "$selectedId-$index-form-v-$seed", + initialValue: rows[index].value, + hintText: "Add Value", + onChanged: (value) { + rows[index] = + rows[index].copyWith(value: value); + _onFieldChange(selectedId!); + }, + colorScheme: + Theme.of(context).colorScheme, + ), + ), + DataCell( + InkWell( + child: Theme.of(context).brightness == + Brightness.dark + ? kIconRemoveDark + : kIconRemoveLight, + onTap: () { + seed = random.nextInt(kRandMax); + if (rows.length == 1) { + setState(() { + rows = [kFormDataEmptyModel]; + }); + } else { + rows.removeAt(index); + } + _onFieldChange(selectedId!); + setState(() {}); + }, + ), + ), + ], + ); + }, + ), + ), ), ), ], diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 7658c8a0..4e2adba6 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -1,7 +1,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:davi/davi.dart'; +import 'package:data_table_2/data_table_2.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/models/models.dart'; @@ -49,101 +49,27 @@ class EditRequestHeadersState extends ConsumerState { ref.read(selectedRequestModelProvider)?.isHeaderEnabledList ?? List.filled(rows.length, true, growable: true); - DaviModel model = DaviModel( - rows: rows, - columns: [ - DaviColumn( - name: 'Checkbox', - width: 30, - cellBuilder: (_, row) { - int idx = row.index; - return CheckBox( - keyId: "$selectedId-$idx-headers-c-$seed", - value: isRowEnabledList[idx], - onChanged: (value) { - setState(() { - isRowEnabledList[idx] = value!; - }); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ); - }, - ), - DaviColumn( - name: 'Header Name', - width: 70, - grow: 1, - cellBuilder: (_, row) { - int idx = row.index; - return HeaderField( - keyId: "$selectedId-$idx-headers-k-$seed", - initialValue: rows[idx].name, - hintText: "Add Header Name", - onChanged: (value) { - rows[idx] = rows[idx].copyWith(name: value); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ); - }, - sortable: false, - ), - DaviColumn( - width: 30, - cellBuilder: (_, row) { - return Text( - "=", - style: kCodeStyle, - ); - }, - ), - DaviColumn( - name: 'Header Value', - grow: 1, - cellBuilder: (_, row) { - int idx = row.index; - return CellField( - keyId: "$selectedId-$idx-headers-v-$seed", - initialValue: rows[idx].value, - hintText: " Add Header Value", - onChanged: (value) { - rows[idx] = rows[idx].copyWith(value: value); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ); - }, - sortable: false, - ), - DaviColumn( - pinStatus: PinStatus.none, - width: 30, - cellBuilder: (_, row) { - return InkWell( - child: Theme.of(context).brightness == Brightness.dark - ? kIconRemoveDark - : kIconRemoveLight, - onTap: () { - seed = random.nextInt(kRandMax); - if (rows.length == 1) { - setState(() { - rows = [ - kNameValueEmptyModel, - ]; - isRowEnabledList = [true]; - }); - } else { - rows.removeAt(row.index); - isRowEnabledList.removeAt(row.index); - } - _onFieldChange(selectedId!); - }, - ); - }, - ), - ], - ); + List columns = const [ + DataColumn2( + label: Text('Checkbox'), + fixedWidth: 30, + ), + DataColumn2( + label: Text('Header Name'), + ), + DataColumn2( + label: Text('='), + fixedWidth: 30, + ), + DataColumn2( + label: Text('Header Value'), + ), + DataColumn2( + label: Text('Remove'), + fixedWidth: 32, + ), + ]; + return Stack( children: [ Container( @@ -155,9 +81,97 @@ class EditRequestHeadersState extends ConsumerState { child: Column( children: [ Expanded( - child: DaviTheme( - data: kTableThemeData, - child: Davi(model), + child: Theme( + data: Theme.of(context) + .copyWith(scrollbarTheme: kDataTableScrollbarTheme), + child: DataTable2( + columnSpacing: 12, + dividerThickness: 0, + horizontalMargin: 0, + headingRowHeight: 0, + dataRowHeight: kDataRowHeight, + bottomMargin: kDataTableBottomPadding, + isVerticalScrollBarVisible: true, + columns: columns, + rows: List.generate( + rows.length, + (index) { + return DataRow( + key: ValueKey("$selectedId-$index-headers-row-$seed"), + cells: [ + DataCell( + CheckBox( + keyId: "$selectedId-$index-headers-c-$seed", + value: isRowEnabledList[index], + onChanged: (value) { + setState(() { + isRowEnabledList[index] = value!; + }); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + HeaderField( + keyId: "$selectedId-$index-headers-k-$seed", + initialValue: rows[index].name, + hintText: "Add Header Name", + onChanged: (value) { + rows[index] = + rows[index].copyWith(name: value); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + Text( + "=", + style: kCodeStyle, + ), + ), + DataCell( + CellField( + keyId: "$selectedId-$index-headers-v-$seed", + initialValue: rows[index].value, + hintText: "Add Header Value", + onChanged: (value) { + rows[index] = + rows[index].copyWith(value: value); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + InkWell( + child: Theme.of(context).brightness == + Brightness.dark + ? kIconRemoveDark + : kIconRemoveLight, + onTap: () { + seed = random.nextInt(kRandMax); + if (rows.length == 1) { + setState(() { + rows = [ + kNameValueEmptyModel, + ]; + isRowEnabledList = [true]; + }); + } else { + rows.removeAt(index); + isRowEnabledList.removeAt(index); + } + _onFieldChange(selectedId!); + }, + ), + ), + ], + ); + }, + ), + ), ), ), ], diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index 01005df6..c6fe63ef 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -1,11 +1,11 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:davi/davi.dart'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/widgets/widgets.dart'; import 'package:apidash/models/models.dart'; import 'package:apidash/consts.dart'; +import 'package:data_table_2/data_table_2.dart'; class EditRequestURLParams extends ConsumerStatefulWidget { const EditRequestURLParams({super.key}); @@ -50,101 +50,26 @@ class EditRequestURLParamsState extends ConsumerState { ref.read(selectedRequestModelProvider)?.isParamEnabledList ?? List.filled(rows.length, true, growable: true); - DaviModel model = DaviModel( - rows: rows, - columns: [ - DaviColumn( - name: 'Checkbox', - width: 30, - cellBuilder: (_, row) { - int idx = row.index; - return CheckBox( - keyId: "$selectedId-$idx-params-c-$seed", - value: isRowEnabledList[idx], - onChanged: (value) { - setState(() { - isRowEnabledList[idx] = value!; - }); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ); - }, - ), - DaviColumn( - name: 'URL Parameter', - width: 70, - grow: 1, - cellBuilder: (_, row) { - int idx = row.index; - return CellField( - keyId: "$selectedId-$idx-params-k-$seed", - initialValue: rows[idx].name, - hintText: "Add URL Parameter", - onChanged: (value) { - rows[idx] = rows[idx].copyWith(name: value); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ); - }, - sortable: false, - ), - DaviColumn( - width: 30, - cellBuilder: (_, row) { - return Text( - "=", - style: kCodeStyle, - ); - }, - ), - DaviColumn( - name: 'Value', - grow: 1, - cellBuilder: (_, row) { - int idx = row.index; - return CellField( - keyId: "$selectedId-$idx-params-v-$seed", - initialValue: rows[idx].value, - hintText: "Add Value", - onChanged: (value) { - rows[idx] = rows[idx].copyWith(value: value); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ); - }, - sortable: false, - ), - DaviColumn( - pinStatus: PinStatus.none, - width: 30, - cellBuilder: (_, row) { - return InkWell( - child: Theme.of(context).brightness == Brightness.dark - ? kIconRemoveDark - : kIconRemoveLight, - onTap: () { - seed = random.nextInt(kRandMax); - if (rows.length == 1) { - setState(() { - rows = [ - kNameValueEmptyModel, - ]; - isRowEnabledList = [true]; - }); - } else { - rows.removeAt(row.index); - isRowEnabledList.removeAt(row.index); - } - _onFieldChange(selectedId!); - }, - ); - }, - ), - ], - ); + List columns = const [ + DataColumn2( + label: Text('Checkbox'), + fixedWidth: 30, + ), + DataColumn2( + label: Text('URL Parameter'), + ), + DataColumn2( + label: Text('='), + fixedWidth: 30, + ), + DataColumn2( + label: Text('Parameter Value'), + ), + DataColumn2( + label: Text('Remove'), + fixedWidth: 32, + ), + ]; return Stack( children: [ Container( @@ -154,11 +79,100 @@ class EditRequestURLParamsState extends ConsumerState { ), margin: kP10, child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded( - child: DaviTheme( - data: kTableThemeData, - child: Davi(model), + child: Theme( + data: Theme.of(context) + .copyWith(scrollbarTheme: kDataTableScrollbarTheme), + child: DataTable2( + columnSpacing: 12, + dividerThickness: 0, + horizontalMargin: 0, + headingRowHeight: 0, + dataRowHeight: kDataRowHeight, + bottomMargin: kDataTableBottomPadding, + isVerticalScrollBarVisible: true, + columns: columns, + rows: List.generate( + rows.length, + (index) { + return DataRow( + key: ValueKey("$selectedId-$index-params-row-$seed"), + cells: [ + DataCell( + CheckBox( + keyId: "$selectedId-$index-params-c-$seed", + value: isRowEnabledList[index], + onChanged: (value) { + setState(() { + isRowEnabledList[index] = value!; + }); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + CellField( + keyId: "$selectedId-$index-params-k-$seed", + initialValue: rows[index].name, + hintText: "Add URL Parameter", + onChanged: (value) { + rows[index] = + rows[index].copyWith(name: value); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + Text( + "=", + style: kCodeStyle, + ), + ), + DataCell( + CellField( + keyId: "$selectedId-$index-params-v-$seed", + initialValue: rows[index].value, + hintText: "Add Value", + onChanged: (value) { + rows[index] = + rows[index].copyWith(value: value); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + InkWell( + child: Theme.of(context).brightness == + Brightness.dark + ? kIconRemoveDark + : kIconRemoveLight, + onTap: () { + seed = random.nextInt(kRandMax); + if (rows.length == 1) { + setState(() { + rows = [ + kNameValueEmptyModel, + ]; + isRowEnabledList = [true]; + }); + } else { + rows.removeAt(index); + isRowEnabledList.removeAt(index); + } + _onFieldChange(selectedId!); + }, + ), + ), + ], + ); + }, + ), + ), ), ), ], diff --git a/lib/widgets/form_data_field.dart b/lib/widgets/form_data_field.dart index 29f210c4..b578617b 100644 --- a/lib/widgets/form_data_field.dart +++ b/lib/widgets/form_data_field.dart @@ -52,7 +52,7 @@ class _FormDataFieldState extends State { ), ), hintText: widget.hintText, - contentPadding: const EdgeInsets.only(bottom: 16), + contentPadding: const EdgeInsets.only(bottom: 13), focusedBorder: UnderlineInputBorder( borderSide: BorderSide( color: colorScheme.primary.withOpacity( diff --git a/lib/widgets/headerfield.dart b/lib/widgets/headerfield.dart index 5bce6c8f..4f0fd096 100644 --- a/lib/widgets/headerfield.dart +++ b/lib/widgets/headerfield.dart @@ -81,6 +81,7 @@ class _HeaderFieldState extends State { hintStyle: kCodeStyle.copyWith( color: colorScheme.outline.withOpacity(kHintOpacity)), hintText: widget.hintText, + contentPadding: const EdgeInsets.only(bottom: 12), focusedBorder: UnderlineInputBorder( borderSide: BorderSide( color: colorScheme.primary.withOpacity( diff --git a/lib/widgets/request_widgets.dart b/lib/widgets/request_widgets.dart index ffac504e..e35df367 100644 --- a/lib/widgets/request_widgets.dart +++ b/lib/widgets/request_widgets.dart @@ -95,6 +95,7 @@ class _RequestPaneState extends State ), ], ), + kVSpacer5, Expanded( child: TabBarView( controller: _controller, diff --git a/lib/widgets/textfields.dart b/lib/widgets/textfields.dart index da68f9e2..c7bac1fb 100644 --- a/lib/widgets/textfields.dart +++ b/lib/widgets/textfields.dart @@ -68,6 +68,7 @@ class CellField extends StatelessWidget { ), ), hintText: hintText, + contentPadding: const EdgeInsets.only(bottom: 12), focusedBorder: UnderlineInputBorder( borderSide: BorderSide( color: clrScheme.primary.withOpacity( diff --git a/pubspec.lock b/pubspec.lock index 4125ed98..f2f67f8e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -233,6 +233,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.4" + data_table_2: + dependency: "direct main" + description: + name: data_table_2 + sha256: fdb0551f103f1daf837bddfde14619fd9e683408833a618c9afabeb533fce88c + url: "https://pub.dev" + source: hosted + version: "2.5.11" davi: dependency: "direct main" description: @@ -508,10 +516,10 @@ packages: dependency: "direct main" description: name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.0" http_multi_server: dependency: transitive description: @@ -633,30 +641,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" - url: "https://pub.dev" - source: hosted - version: "10.0.0" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 - url: "https://pub.dev" - source: hosted - version: "2.0.1" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 - url: "https://pub.dev" - source: hosted - version: "2.0.1" lints: dependency: transitive description: @@ -693,26 +677,26 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.5.0" meta: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.10.0" mime: dependency: transitive description: @@ -789,10 +773,10 @@ packages: dependency: "direct main" description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.8.3" path_parsing: dependency: transitive description: @@ -909,10 +893,10 @@ packages: dependency: transitive description: name: pointer_interceptor_web - sha256: a6237528b46c411d8d55cdfad8fcb3269fc4cbb26060b14bff94879165887d1e + sha256: "9386e064097fd16419e935c23f08f35b58e6aaec155dd39bd6a003b88f9c14b4" url: "https://pub.dev" source: hosted - version: "0.10.2" + version: "0.10.1+2" pointycastle: dependency: transitive description: @@ -1234,10 +1218,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "3692a459204a33e04bc94f5fb91158faf4f2c8903281ddd82915adecdb1a901d" + sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.2.3" url_launcher_windows: dependency: transitive description: @@ -1306,10 +1290,10 @@ packages: dependency: "direct main" description: name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.3.0" web_socket_channel: dependency: transitive description: @@ -1376,5 +1360,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.3.0 <4.0.0" - flutter: ">=3.19.0" + dart: ">=3.2.3 <4.0.0" + flutter: ">=3.16.0" diff --git a/pubspec.yaml b/pubspec.yaml index ab250f26..9b2e354c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -56,6 +56,7 @@ dependencies: dart_style: ^2.3.4 json_text_field: ^1.1.0 csv: ^5.1.1 + data_table_2: ^2.5.11 dev_dependencies: flutter_test: From 266e36cf668968fee8ce62d813bece3528cdbe2f Mon Sep 17 00:00:00 2001 From: DenserMeerkat Date: Fri, 15 Mar 2024 03:18:20 +0530 Subject: [PATCH 009/138] rafactor: remove davi --- lib/consts.dart | 14 -------------- pubspec.yaml | 1 - 2 files changed, 15 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index efde9820..deb14977 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:davi/davi.dart'; const kDiscordUrl = "https://bit.ly/heyfoss"; const kGitUrl = "https://github.com/foss42/apidash"; @@ -120,19 +119,6 @@ const kDataTableScrollbarTheme = ScrollbarThemeData( ); const kDataTableBottomPadding = 80.0; const kDataRowHeight = 36.0; -const kTableThemeData = DaviThemeData( - columnDividerThickness: 1, - columnDividerColor: kColorTransparent, - row: RowThemeData( - dividerColor: kColorTransparent, - ), - decoration: BoxDecoration( - border: Border(), - ), - header: HeaderThemeData( - visible: false, - ), -); const kIconRemoveDark = Icon( Icons.remove_circle, diff --git a/pubspec.yaml b/pubspec.yaml index 9b2e354c..cc5a6b0a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,6 @@ dependencies: url_launcher: ^6.1.12 flutter_riverpod: ^2.3.7 uuid: ^4.1.0 - davi: ^3.4.1 http: ^1.1.0 http_parser: ^4.0.2 collection: ^1.17.2 From 5beb51d2f4bc891902dd28cfc733b2ff1e96ea57 Mon Sep 17 00:00:00 2001 From: DenserMeerkat Date: Sat, 16 Mar 2024 15:52:29 +0530 Subject: [PATCH 010/138] fix: textstyle height, keyId --- .../request_pane/request_form_data.dart | 6 +- .../request_pane/request_headers.dart | 4 +- .../request_pane/request_params.dart | 2 +- lib/widgets/form_data_field.dart | 4 +- lib/widgets/headerfield.dart | 6 +- lib/widgets/textfields.dart | 2 + pubspec.lock | 76 ++++++++++--------- 7 files changed, 58 insertions(+), 42 deletions(-) diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart index 3b9baf9f..de703930 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart @@ -81,9 +81,9 @@ class _FormDataBodyState extends ConsumerState { Theme( data: Theme.of(context), child: FormDataField( - keyId: "$selectedId-$index-form-v-$seed", + keyId: "$selectedId-$index-form-k-$seed", initialValue: rows[index].name, - hintText: "Add Key", + hintText: " Add Key", onChanged: (value) { rows[index] = rows[index].copyWith( name: value, @@ -178,7 +178,7 @@ class _FormDataBodyState extends ConsumerState { : CellField( keyId: "$selectedId-$index-form-v-$seed", initialValue: rows[index].value, - hintText: "Add Value", + hintText: " Add Value", onChanged: (value) { rows[index] = rows[index].copyWith(value: value); diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 4e2adba6..52648d4b 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -37,7 +37,7 @@ class EditRequestHeadersState extends ConsumerState { @override Widget build(BuildContext context) { final selectedId = ref.watch(selectedIdStateProvider); - final length = ref.watch(selectedRequestModelProvider + ref.watch(selectedRequestModelProvider .select((value) => value?.requestHeaders?.length)); var rH = ref.read(selectedRequestModelProvider)?.requestHeaders; rows = (rH == null || rH.isEmpty) @@ -135,7 +135,7 @@ class EditRequestHeadersState extends ConsumerState { CellField( keyId: "$selectedId-$index-headers-v-$seed", initialValue: rows[index].value, - hintText: "Add Header Value", + hintText: " Add Header Value", onChanged: (value) { rows[index] = rows[index].copyWith(value: value); diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index c6fe63ef..6c673db5 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -38,7 +38,7 @@ class EditRequestURLParamsState extends ConsumerState { @override Widget build(BuildContext context) { final selectedId = ref.watch(selectedIdStateProvider); - final length = ref.watch(selectedRequestModelProvider + ref.watch(selectedRequestModelProvider .select((value) => value?.requestParams?.length)); var rP = ref.read(selectedRequestModelProvider)?.requestParams; rows = (rP == null || rP.isEmpty) diff --git a/lib/widgets/form_data_field.dart b/lib/widgets/form_data_field.dart index b578617b..76c40be4 100644 --- a/lib/widgets/form_data_field.dart +++ b/lib/widgets/form_data_field.dart @@ -43,16 +43,18 @@ class _FormDataFieldState extends State { initialValue: widget.initialValue, key: Key(widget.keyId), style: kCodeStyle.copyWith( + height: 1.8, color: colorScheme.onSurface, ), decoration: InputDecoration( hintStyle: kCodeStyle.copyWith( + height: 1.8, color: colorScheme.outline.withOpacity( kHintOpacity, ), ), hintText: widget.hintText, - contentPadding: const EdgeInsets.only(bottom: 13), + contentPadding: const EdgeInsets.only(bottom: 12), focusedBorder: UnderlineInputBorder( borderSide: BorderSide( color: colorScheme.primary.withOpacity( diff --git a/lib/widgets/headerfield.dart b/lib/widgets/headerfield.dart index 4f0fd096..ec0f3a48 100644 --- a/lib/widgets/headerfield.dart +++ b/lib/widgets/headerfield.dart @@ -76,9 +76,13 @@ class _HeaderFieldState extends State { onChanged: widget.onChanged, controller: controller, focusNode: focusNode, - style: kCodeStyle.copyWith(color: colorScheme.onSurface), + style: kCodeStyle.copyWith( + height: 1.6, + color: colorScheme.onSurface, + ), decoration: InputDecoration( hintStyle: kCodeStyle.copyWith( + height: 1.6, color: colorScheme.outline.withOpacity(kHintOpacity)), hintText: widget.hintText, contentPadding: const EdgeInsets.only(bottom: 12), diff --git a/lib/widgets/textfields.dart b/lib/widgets/textfields.dart index c7bac1fb..cb5e224b 100644 --- a/lib/widgets/textfields.dart +++ b/lib/widgets/textfields.dart @@ -59,10 +59,12 @@ class CellField extends StatelessWidget { key: Key(keyId), initialValue: initialValue, style: kCodeStyle.copyWith( + height: 1.6, color: clrScheme.onSurface, ), decoration: InputDecoration( hintStyle: kCodeStyle.copyWith( + height: 1.6, color: clrScheme.outline.withOpacity( kHintOpacity, ), diff --git a/pubspec.lock b/pubspec.lock index f2f67f8e..ac27b7a9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -49,14 +49,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.18" - axis_layout: - dependency: transitive - description: - name: axis_layout - sha256: "9ba44f279f39121065d811e72da892de86f5613d68eb0b295f60d021ea8f2a59" - url: "https://pub.dev" - source: hosted - version: "1.0.1" barcode: dependency: transitive description: @@ -241,14 +233,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.5.11" - davi: - dependency: "direct main" - description: - name: davi - sha256: "4105870281c4c33e8e017e21e212b96fd2637b4c1a35b2a56f14aaa4acdf6f0d" - url: "https://pub.dev" - source: hosted - version: "3.4.1" eventify: dependency: transitive description: @@ -516,10 +500,10 @@ packages: dependency: "direct main" description: name: http - sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" http_multi_server: dependency: transitive description: @@ -641,6 +625,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: transitive description: @@ -677,26 +685,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" mime: dependency: transitive description: @@ -773,10 +781,10 @@ packages: dependency: "direct main" description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" path_parsing: dependency: transitive description: @@ -893,10 +901,10 @@ packages: dependency: transitive description: name: pointer_interceptor_web - sha256: "9386e064097fd16419e935c23f08f35b58e6aaec155dd39bd6a003b88f9c14b4" + sha256: a6237528b46c411d8d55cdfad8fcb3269fc4cbb26060b14bff94879165887d1e url: "https://pub.dev" source: hosted - version: "0.10.1+2" + version: "0.10.2" pointycastle: dependency: transitive description: @@ -1218,10 +1226,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b + sha256: "3692a459204a33e04bc94f5fb91158faf4f2c8903281ddd82915adecdb1a901d" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.0" url_launcher_windows: dependency: transitive description: @@ -1290,10 +1298,10 @@ packages: dependency: "direct main" description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.5.1" web_socket_channel: dependency: transitive description: @@ -1360,5 +1368,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.3 <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" From c51018baac0e1bc940d2d8ab4f25f798cc917f41 Mon Sep 17 00:00:00 2001 From: Mohammed Abdul Razak Wahab Date: Sat, 16 Mar 2024 22:15:18 +0530 Subject: [PATCH 011/138] updated video preview logic --- lib/consts.dart | 5 +- lib/widgets/previewer.dart | 8 +- lib/widgets/video_previewer.dart | 147 +++++++++++++++++++++++++++++++ pubspec.lock | 64 ++++++++++++++ pubspec.yaml | 5 +- test/widgets/previewer_test.dart | 6 +- 6 files changed, 228 insertions(+), 7 deletions(-) create mode 100644 lib/widgets/video_previewer.dart diff --git a/lib/consts.dart b/lib/consts.dart index e3d2dc6b..d188e4a2 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -16,7 +16,7 @@ final kIsLinux = !kIsWeb && Platform.isLinux; final kIsApple = !kIsWeb && (Platform.isIOS || Platform.isMacOS); final kIsDesktop = !kIsWeb && (Platform.isMacOS || Platform.isWindows || Platform.isLinux); - +final kIsRunningTests = Platform.environment.containsKey('FLUTTER_TEST'); final kIsIOS = !kIsWeb && Platform.isIOS; final kIsAndroid = !kIsWeb && Platform.isAndroid; final kIsMobile = !kIsWeb && (Platform.isIOS || Platform.isAndroid); @@ -496,6 +496,9 @@ const kMimeTypeRaiseIssue = const kUnexpectedRaiseIssue = "\nIf the behaviour is unexpected, please raise an issue in API Dash GitHub repo so that we can resolve it."; +const kVideoError = + "There seems to be an issue playing this video. Please raise an issue in API Dash GitHub repo so that we can resolve it."; + const kImageError = "There seems to be an issue rendering this image. Please raise an issue in API Dash GitHub repo so that we can resolve it."; diff --git a/lib/widgets/previewer.dart b/lib/widgets/previewer.dart index dd2f5186..ac213b50 100644 --- a/lib/widgets/previewer.dart +++ b/lib/widgets/previewer.dart @@ -8,6 +8,7 @@ import 'error_message.dart'; import 'uint8_audio_player.dart'; import 'json_previewer.dart'; import 'csv_previewer.dart'; +import 'video_previewer.dart'; import '../consts.dart'; class Previewer extends StatefulWidget { @@ -86,7 +87,12 @@ class _PreviewerState extends State { return CsvPreviewer(body: widget.body); } if (widget.type == kTypeVideo) { - // TODO: Video Player + try { + var preview = VideoPreviewer(videoBytes: widget.bytes); + return preview; + } catch (e) { + return const ErrorMessage(message: kVideoError); + } } String message = widget.hasRaw ? "$kMimeTypeRawRaiseIssueStart${widget.type}/${widget.subtype}$kMimeTypeRaiseIssue" diff --git a/lib/widgets/video_previewer.dart b/lib/widgets/video_previewer.dart new file mode 100644 index 00000000..a6461b5e --- /dev/null +++ b/lib/widgets/video_previewer.dart @@ -0,0 +1,147 @@ +import 'dart:io'; +import 'dart:typed_data'; +import 'package:apidash/consts.dart'; +import 'package:fvp/fvp.dart' as fvp; +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; +import 'package:video_player/video_player.dart'; +import 'package:path_provider/path_provider.dart'; + +class VideoPreviewer extends StatefulWidget { + const VideoPreviewer({ + super.key, + required this.videoBytes, + }); + + final Uint8List videoBytes; + + @override + State createState() => _VideoPreviewerState(); +} + +class _VideoPreviewerState extends State { + VideoPlayerController? _videoController; + bool _isPlaying = false; + File? _tempVideoFile; + bool _showControls = false; + + @override + void initState() { + super.initState(); + registerWithAllPlatforms(); + _initializeVideoPlayer(); + } + + void registerWithAllPlatforms() { + try { + fvp.registerWith(); + } catch (e) { + // pass + } + } + + void _initializeVideoPlayer() async { + final tempDir = await getTemporaryDirectory(); + _tempVideoFile = File( + '${tempDir.path}/temp_video_${DateTime.now().millisecondsSinceEpoch}.mp4'); + try { + await _tempVideoFile?.writeAsBytes(widget.videoBytes); + _videoController = VideoPlayerController.file(_tempVideoFile!) + ..initialize().then((_) { + if (mounted) { + setState(() { + _videoController!.play(); + _videoController!.setLooping(true); + }); + } + }); + } catch (e) { + return; + } + } + + @override + Widget build(BuildContext context) { + final iconColor = Theme.of(context).iconTheme.color; + final progressBarColors = VideoProgressColors( + playedColor: iconColor!, + bufferedColor: iconColor.withOpacity(0.5), + backgroundColor: iconColor.withOpacity(0.3), + ); + return Scaffold( + body: MouseRegion( + onEnter: (_) => setState(() => _showControls = true), + onExit: (_) => setState(() => _showControls = false), + child: Stack( + children: [ + Center( + child: _videoController?.value.isInitialized == true + ? AspectRatio( + aspectRatio: _videoController!.value.aspectRatio, + child: VideoPlayer(_videoController!), + ) + : const CircularProgressIndicator(), + ), + Positioned( + left: 0, + right: 0, + bottom: 0, + child: _videoController?.value.isInitialized == true + ? SizedBox( + height: 50.0, + child: VideoProgressIndicator( + _videoController!, + allowScrubbing: true, + padding: const EdgeInsets.all(20), + colors: progressBarColors, + ), + ) + : Container(height: 0), + ), + if (_showControls) + Center( + child: GestureDetector( + onTap: () { + if (_videoController!.value.isPlaying) { + _videoController!.pause(); + } else { + _videoController!.play(); + } + setState(() { + _isPlaying = !_isPlaying; + }); + }, + child: Container( + color: Colors.transparent, + child: Icon( + _isPlaying ? Icons.play_arrow : Icons.pause, + size: 64, + color: iconColor, + ), + ), + ), + ), + ], + ), + ), + ); + } + + @override + void dispose() { + _videoController?.pause(); + _videoController?.dispose(); + if (!kIsRunningTests) { + Future.delayed(const Duration(seconds: 1), () async { + try { + if (_tempVideoFile != null) { + await _tempVideoFile!.delete(); + } + } catch (e) { + return; + } + }); + } + super.dispose(); + } +} diff --git a/pubspec.lock b/pubspec.lock index a4e54dfb..af770260 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -217,6 +217,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + csslib: + dependency: transitive + description: + name: csslib + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + url: "https://pub.dev" + source: hosted + version: "1.0.0" csv: dependency: "direct main" description: @@ -448,6 +456,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.0" + fvp: + dependency: "direct main" + description: + name: fvp + sha256: "995328479ba4641da6760ddc84a168db157a3b9db4f0417fa68713d99344a146" + url: "https://pub.dev" + source: hosted + version: "0.14.0" glob: dependency: transitive description: @@ -496,6 +512,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + html: + dependency: transitive + description: + name: html + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + url: "https://pub.dev" + source: hosted + version: "0.15.4" html_unescape: dependency: transitive description: @@ -1294,6 +1318,46 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + video_player: + dependency: "direct main" + description: + name: video_player + sha256: afc65f4b8bcb2c188f64a591f84fb471f4f2e19fc607c65fd8d2f8fedb3dec23 + url: "https://pub.dev" + source: hosted + version: "2.8.3" + video_player_android: + dependency: transitive + description: + name: video_player_android + sha256: "4dd9b8b86d70d65eecf3dcabfcdfbb9c9115d244d022654aba49a00336d540c2" + url: "https://pub.dev" + source: hosted + version: "2.4.12" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + sha256: "309e3962795e761be010869bae65c0b0e45b5230c5cee1bec72197ca7db040ed" + url: "https://pub.dev" + source: hosted + version: "2.5.6" + video_player_platform_interface: + dependency: "direct main" + description: + name: video_player_platform_interface + sha256: "236454725fafcacf98f0f39af0d7c7ab2ce84762e3b63f2cbb3ef9a7e0550bc6" + url: "https://pub.dev" + source: hosted + version: "6.2.2" + video_player_web: + dependency: transitive + description: + name: video_player_web + sha256: "41245cef5ef29c4585dbabcbcbe9b209e34376642c7576cabf11b4ad9289d6e4" + url: "https://pub.dev" + source: hosted + version: "2.3.0" vm_service: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 6f78ae1e..1556bc6c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: multi_split_view: ^2.4.0 url_launcher: ^6.2.5 flutter_riverpod: ^2.5.1 - riverpod: ^2.5.1 + riverpod: ^2.5.1 uuid: ^4.3.3 davi: ^3.4.1 http: ^1.2.1 @@ -44,6 +44,9 @@ dependencies: package_info_plus: ^5.0.1 flutter_typeahead: ^5.2.0 provider: ^6.1.2 + fvp: ^0.14.0 + video_player: ^2.3.2 + video_player_platform_interface: ^6.2.2 json_data_explorer: git: url: https://github.com/foss42/json_data_explorer.git diff --git a/test/widgets/previewer_test.dart b/test/widgets/previewer_test.dart index c26793bb..c8a33f62 100644 --- a/test/widgets/previewer_test.dart +++ b/test/widgets/previewer_test.dart @@ -5,6 +5,7 @@ import 'package:apidash/consts.dart'; import 'package:flutter/foundation.dart'; import 'package:printing/printing.dart' show PdfPreview; import 'package:flutter_svg/flutter_svg.dart' show SvgPicture; +import 'package:apidash/widgets/video_previewer.dart'; import '../test_consts.dart'; void main() { @@ -63,10 +64,7 @@ void main() { ), ), ); - - expect( - find.text("${kMimeTypeRaiseIssueStart}video/H264$kMimeTypeRaiseIssue"), - findsOneWidget); + expect(find.byType(VideoPreviewer), findsOneWidget); }); testWidgets('Testing when type/subtype is model/step+xml', (tester) async { From 6724db3be67f7c4749e2a348c461b5d7c695a754 Mon Sep 17 00:00:00 2001 From: DenserMeerkat Date: Sun, 17 Mar 2024 04:06:17 +0530 Subject: [PATCH 012/138] fix: form data columns --- .../request_pane/request_form_data.dart | 151 ++++++++---------- .../request_pane/request_headers.dart | 2 +- .../request_pane/request_params.dart | 2 +- lib/widgets/form_data_field.dart | 2 - lib/widgets/headerfield.dart | 2 - lib/widgets/textfields.dart | 2 - pubspec.yaml | 4 +- 7 files changed, 69 insertions(+), 96 deletions(-) diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart index de703930..b83666a6 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart @@ -34,13 +34,19 @@ class _FormDataBodyState extends ConsumerState { List columns = const [ DataColumn2( label: Text('Key'), + size: ColumnSize.M, ), DataColumn2( label: Text('='), - fixedWidth: 30, + fixedWidth: 20, + ), + DataColumn2( + label: Text('Type'), + fixedWidth: 70, ), DataColumn2( label: Text('Value'), + size: ColumnSize.L, ), DataColumn2( label: Text('Remove'), @@ -78,30 +84,16 @@ class _FormDataBodyState extends ConsumerState { key: ValueKey("$selectedId-$index-form-row-$seed"), cells: [ DataCell( - Theme( - data: Theme.of(context), - child: FormDataField( - keyId: "$selectedId-$index-form-k-$seed", - initialValue: rows[index].name, - hintText: " Add Key", - onChanged: (value) { - rows[index] = rows[index].copyWith( - name: value, - ); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - formDataType: rows[index].type, - onFormDataTypeChanged: (value) { - rows[index] = rows[index].copyWith( - type: value ?? FormDataType.text, - ); - rows[index] = - rows[index].copyWith(value: ""); - setState(() {}); - _onFieldChange(selectedId!); - }, - ), + CellField( + keyId: "$selectedId-$index-form-k-$seed", + initialValue: rows[index].name, + hintText: " Add Key", + onChanged: (value) { + rows[index] = + rows[index].copyWith(name: value); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, ), ), DataCell( @@ -110,69 +102,56 @@ class _FormDataBodyState extends ConsumerState { style: kCodeStyle, ), ), + DataCell( + DropdownButtonFormData( + formDataType: rows[index].type, + onChanged: (value) { + rows[index] = rows[index].copyWith( + type: value ?? FormDataType.text, + ); + rows[index] = rows[index].copyWith(value: ""); + setState(() {}); + _onFieldChange(selectedId!); + }, + ), + ), DataCell( rows[index].type == FormDataType.file - ? Align( - alignment: Alignment.centerLeft, - child: Row( - children: [ - Expanded( - child: Theme( - data: Theme.of(context), - child: ElevatedButton.icon( - icon: const Icon( - Icons.snippet_folder_rounded, - size: 20, - ), - style: ButtonStyle( - shape: - MaterialStatePropertyAll( - RoundedRectangleBorder( - borderRadius: - BorderRadius.circular( - 6), - ), - ), - ), - onPressed: () async { - var pickedResult = - await pickFile(); - if (pickedResult != null && - pickedResult - .files.isNotEmpty && - pickedResult.files.first - .path != - null) { - rows[index] = - rows[index].copyWith( - value: pickedResult - .files.first.path!, - ); - setState(() {}); - _onFieldChange(selectedId!); - } - }, - label: Text( - (rows[index].type == - FormDataType - .file && - rows[index] - .value - .isNotEmpty) - ? rows[index] - .value - .toString() - : "Select File", - textAlign: TextAlign.center, - overflow: - TextOverflow.ellipsis, - style: - kFormDataButtonLabelTextStyle, - ), - ), - ), - ), - ], + ? ElevatedButton.icon( + icon: const Icon( + Icons.snippet_folder_rounded, + size: 20, + ), + style: ElevatedButton.styleFrom( + minimumSize: const Size.fromHeight( + kDataRowHeight), + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(6), + ), + ), + onPressed: () async { + var pickedResult = await pickFile(); + if (pickedResult != null && + pickedResult.files.isNotEmpty && + pickedResult.files.first.path != + null) { + rows[index] = rows[index].copyWith( + value: + pickedResult.files.first.path!, + ); + setState(() {}); + _onFieldChange(selectedId!); + } + }, + label: Text( + (rows[index].type == + FormDataType.file && + rows[index].value.isNotEmpty) + ? rows[index].value.toString() + : "Select File", + overflow: TextOverflow.ellipsis, + style: kFormDataButtonLabelTextStyle, ), ) : CellField( diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 52648d4b..2fde22ab 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -59,7 +59,7 @@ class EditRequestHeadersState extends ConsumerState { ), DataColumn2( label: Text('='), - fixedWidth: 30, + fixedWidth: 22, ), DataColumn2( label: Text('Header Value'), diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index 6c673db5..4f122798 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -60,7 +60,7 @@ class EditRequestURLParamsState extends ConsumerState { ), DataColumn2( label: Text('='), - fixedWidth: 30, + fixedWidth: 22, ), DataColumn2( label: Text('Parameter Value'), diff --git a/lib/widgets/form_data_field.dart b/lib/widgets/form_data_field.dart index 76c40be4..7b7751fb 100644 --- a/lib/widgets/form_data_field.dart +++ b/lib/widgets/form_data_field.dart @@ -43,12 +43,10 @@ class _FormDataFieldState extends State { initialValue: widget.initialValue, key: Key(widget.keyId), style: kCodeStyle.copyWith( - height: 1.8, color: colorScheme.onSurface, ), decoration: InputDecoration( hintStyle: kCodeStyle.copyWith( - height: 1.8, color: colorScheme.outline.withOpacity( kHintOpacity, ), diff --git a/lib/widgets/headerfield.dart b/lib/widgets/headerfield.dart index ec0f3a48..3d60caac 100644 --- a/lib/widgets/headerfield.dart +++ b/lib/widgets/headerfield.dart @@ -77,12 +77,10 @@ class _HeaderFieldState extends State { controller: controller, focusNode: focusNode, style: kCodeStyle.copyWith( - height: 1.6, color: colorScheme.onSurface, ), decoration: InputDecoration( hintStyle: kCodeStyle.copyWith( - height: 1.6, color: colorScheme.outline.withOpacity(kHintOpacity)), hintText: widget.hintText, contentPadding: const EdgeInsets.only(bottom: 12), diff --git a/lib/widgets/textfields.dart b/lib/widgets/textfields.dart index cb5e224b..c7bac1fb 100644 --- a/lib/widgets/textfields.dart +++ b/lib/widgets/textfields.dart @@ -59,12 +59,10 @@ class CellField extends StatelessWidget { key: Key(keyId), initialValue: initialValue, style: kCodeStyle.copyWith( - height: 1.6, color: clrScheme.onSurface, ), decoration: InputDecoration( hintStyle: kCodeStyle.copyWith( - height: 1.6, color: clrScheme.outline.withOpacity( kHintOpacity, ), diff --git a/pubspec.yaml b/pubspec.yaml index 79ee83ab..9c30cd6f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: multi_split_view: ^2.4.0 url_launcher: ^6.2.5 flutter_riverpod: ^2.5.1 - riverpod: ^2.5.1 + riverpod: ^2.5.1 uuid: ^4.3.3 http: ^1.2.1 http_parser: ^4.0.2 @@ -56,7 +56,7 @@ dependencies: json_text_field: ^1.1.0 csv: ^6.0.0 data_table_2: ^2.5.11 - + dependency_overrides: web: ^0.5.0 From c6292cb0839aef990a4a57fd22dfc60ef49a7732 Mon Sep 17 00:00:00 2001 From: DenserMeerkat Date: Sun, 17 Mar 2024 04:20:17 +0530 Subject: [PATCH 013/138] refactor: remove form_data_field --- lib/consts.dart | 2 +- .../request_pane/request_form_data.dart | 223 +++++++++--------- .../request_pane/request_headers.dart | 157 ++++++------ .../request_pane/request_params.dart | 158 ++++++------- lib/widgets/form_data_field.dart | 83 ------- lib/widgets/widgets.dart | 1 - test/widgets/form_data_field_test.dart | 21 -- 7 files changed, 266 insertions(+), 379 deletions(-) delete mode 100644 lib/widgets/form_data_field.dart delete mode 100644 test/widgets/form_data_field_test.dart diff --git a/lib/consts.dart b/lib/consts.dart index 866f7de1..25778b2f 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -118,7 +118,7 @@ const kDataTableScrollbarTheme = ScrollbarThemeData( crossAxisMargin: -4, ); const kDataTableBottomPadding = 80.0; -const kDataRowHeight = 36.0; +const kDataTableRowHeight = 36.0; const kIconRemoveDark = Icon( Icons.remove_circle, diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart index b83666a6..a0018b73 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart @@ -54,6 +54,112 @@ class _FormDataBodyState extends ConsumerState { ), ]; + List dataRows = List.generate( + rows.length, + (index) { + return DataRow( + key: ValueKey("$selectedId-$index-form-row-$seed"), + cells: [ + DataCell( + CellField( + keyId: "$selectedId-$index-form-k-$seed", + initialValue: rows[index].name, + hintText: " Add Key", + onChanged: (value) { + rows[index] = rows[index].copyWith(name: value); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + Text( + "=", + style: kCodeStyle, + ), + ), + DataCell( + DropdownButtonFormData( + formDataType: rows[index].type, + onChanged: (value) { + rows[index] = rows[index].copyWith( + type: value ?? FormDataType.text, + ); + rows[index] = rows[index].copyWith(value: ""); + setState(() {}); + _onFieldChange(selectedId!); + }, + ), + ), + DataCell( + rows[index].type == FormDataType.file + ? ElevatedButton.icon( + icon: const Icon( + Icons.snippet_folder_rounded, + size: 20, + ), + style: ElevatedButton.styleFrom( + minimumSize: const Size.fromHeight(kDataTableRowHeight), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), + ), + onPressed: () async { + var pickedResult = await pickFile(); + if (pickedResult != null && + pickedResult.files.isNotEmpty && + pickedResult.files.first.path != null) { + rows[index] = rows[index].copyWith( + value: pickedResult.files.first.path!, + ); + setState(() {}); + _onFieldChange(selectedId!); + } + }, + label: Text( + (rows[index].type == FormDataType.file && + rows[index].value.isNotEmpty) + ? rows[index].value.toString() + : "Select File", + overflow: TextOverflow.ellipsis, + style: kFormDataButtonLabelTextStyle, + ), + ) + : CellField( + keyId: "$selectedId-$index-form-v-$seed", + initialValue: rows[index].value, + hintText: " Add Value", + onChanged: (value) { + rows[index] = rows[index].copyWith(value: value); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + InkWell( + child: Theme.of(context).brightness == Brightness.dark + ? kIconRemoveDark + : kIconRemoveLight, + onTap: () { + seed = random.nextInt(kRandMax); + if (rows.length == 1) { + setState(() { + rows = [kFormDataEmptyModel]; + }); + } else { + rows.removeAt(index); + } + _onFieldChange(selectedId!); + setState(() {}); + }, + ), + ), + ], + ); + }, + ); + return Stack( children: [ Container( @@ -73,124 +179,11 @@ class _FormDataBodyState extends ConsumerState { dividerThickness: 0, horizontalMargin: 0, headingRowHeight: 0, - dataRowHeight: kDataRowHeight, + dataRowHeight: kDataTableRowHeight, bottomMargin: kDataTableBottomPadding, isVerticalScrollBarVisible: true, columns: columns, - rows: List.generate( - rows.length, - (index) { - return DataRow( - key: ValueKey("$selectedId-$index-form-row-$seed"), - cells: [ - DataCell( - CellField( - keyId: "$selectedId-$index-form-k-$seed", - initialValue: rows[index].name, - hintText: " Add Key", - onChanged: (value) { - rows[index] = - rows[index].copyWith(name: value); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ), - ), - DataCell( - Text( - "=", - style: kCodeStyle, - ), - ), - DataCell( - DropdownButtonFormData( - formDataType: rows[index].type, - onChanged: (value) { - rows[index] = rows[index].copyWith( - type: value ?? FormDataType.text, - ); - rows[index] = rows[index].copyWith(value: ""); - setState(() {}); - _onFieldChange(selectedId!); - }, - ), - ), - DataCell( - rows[index].type == FormDataType.file - ? ElevatedButton.icon( - icon: const Icon( - Icons.snippet_folder_rounded, - size: 20, - ), - style: ElevatedButton.styleFrom( - minimumSize: const Size.fromHeight( - kDataRowHeight), - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(6), - ), - ), - onPressed: () async { - var pickedResult = await pickFile(); - if (pickedResult != null && - pickedResult.files.isNotEmpty && - pickedResult.files.first.path != - null) { - rows[index] = rows[index].copyWith( - value: - pickedResult.files.first.path!, - ); - setState(() {}); - _onFieldChange(selectedId!); - } - }, - label: Text( - (rows[index].type == - FormDataType.file && - rows[index].value.isNotEmpty) - ? rows[index].value.toString() - : "Select File", - overflow: TextOverflow.ellipsis, - style: kFormDataButtonLabelTextStyle, - ), - ) - : CellField( - keyId: "$selectedId-$index-form-v-$seed", - initialValue: rows[index].value, - hintText: " Add Value", - onChanged: (value) { - rows[index] = - rows[index].copyWith(value: value); - _onFieldChange(selectedId!); - }, - colorScheme: - Theme.of(context).colorScheme, - ), - ), - DataCell( - InkWell( - child: Theme.of(context).brightness == - Brightness.dark - ? kIconRemoveDark - : kIconRemoveLight, - onTap: () { - seed = random.nextInt(kRandMax); - if (rows.length == 1) { - setState(() { - rows = [kFormDataEmptyModel]; - }); - } else { - rows.removeAt(index); - } - _onFieldChange(selectedId!); - setState(() {}); - }, - ), - ), - ], - ); - }, - ), + rows: dataRows, ), ), ), diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 2fde22ab..dde0020b 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -70,6 +70,82 @@ class EditRequestHeadersState extends ConsumerState { ), ]; + List dataRows = List.generate( + rows.length, + (index) { + return DataRow( + key: ValueKey("$selectedId-$index-headers-row-$seed"), + cells: [ + DataCell( + CheckBox( + keyId: "$selectedId-$index-headers-c-$seed", + value: isRowEnabledList[index], + onChanged: (value) { + setState(() { + isRowEnabledList[index] = value!; + }); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + HeaderField( + keyId: "$selectedId-$index-headers-k-$seed", + initialValue: rows[index].name, + hintText: "Add Header Name", + onChanged: (value) { + rows[index] = rows[index].copyWith(name: value); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + Text( + "=", + style: kCodeStyle, + ), + ), + DataCell( + CellField( + keyId: "$selectedId-$index-headers-v-$seed", + initialValue: rows[index].value, + hintText: " Add Header Value", + onChanged: (value) { + rows[index] = rows[index].copyWith(value: value); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + InkWell( + child: Theme.of(context).brightness == Brightness.dark + ? kIconRemoveDark + : kIconRemoveLight, + onTap: () { + seed = random.nextInt(kRandMax); + if (rows.length == 1) { + setState(() { + rows = [ + kNameValueEmptyModel, + ]; + isRowEnabledList = [true]; + }); + } else { + rows.removeAt(index); + isRowEnabledList.removeAt(index); + } + _onFieldChange(selectedId!); + }, + ), + ), + ], + ); + }, + ); + return Stack( children: [ Container( @@ -89,88 +165,11 @@ class EditRequestHeadersState extends ConsumerState { dividerThickness: 0, horizontalMargin: 0, headingRowHeight: 0, - dataRowHeight: kDataRowHeight, + dataRowHeight: kDataTableRowHeight, bottomMargin: kDataTableBottomPadding, isVerticalScrollBarVisible: true, columns: columns, - rows: List.generate( - rows.length, - (index) { - return DataRow( - key: ValueKey("$selectedId-$index-headers-row-$seed"), - cells: [ - DataCell( - CheckBox( - keyId: "$selectedId-$index-headers-c-$seed", - value: isRowEnabledList[index], - onChanged: (value) { - setState(() { - isRowEnabledList[index] = value!; - }); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ), - ), - DataCell( - HeaderField( - keyId: "$selectedId-$index-headers-k-$seed", - initialValue: rows[index].name, - hintText: "Add Header Name", - onChanged: (value) { - rows[index] = - rows[index].copyWith(name: value); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ), - ), - DataCell( - Text( - "=", - style: kCodeStyle, - ), - ), - DataCell( - CellField( - keyId: "$selectedId-$index-headers-v-$seed", - initialValue: rows[index].value, - hintText: " Add Header Value", - onChanged: (value) { - rows[index] = - rows[index].copyWith(value: value); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ), - ), - DataCell( - InkWell( - child: Theme.of(context).brightness == - Brightness.dark - ? kIconRemoveDark - : kIconRemoveLight, - onTap: () { - seed = random.nextInt(kRandMax); - if (rows.length == 1) { - setState(() { - rows = [ - kNameValueEmptyModel, - ]; - isRowEnabledList = [true]; - }); - } else { - rows.removeAt(index); - isRowEnabledList.removeAt(index); - } - _onFieldChange(selectedId!); - }, - ), - ), - ], - ); - }, - ), + rows: dataRows, ), ), ), diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index 4f122798..d0552e44 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -70,6 +70,83 @@ class EditRequestURLParamsState extends ConsumerState { fixedWidth: 32, ), ]; + + List dataRows = List.generate( + rows.length, + (index) { + return DataRow( + key: ValueKey("$selectedId-$index-params-row-$seed"), + cells: [ + DataCell( + CheckBox( + keyId: "$selectedId-$index-params-c-$seed", + value: isRowEnabledList[index], + onChanged: (value) { + setState(() { + isRowEnabledList[index] = value!; + }); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + CellField( + keyId: "$selectedId-$index-params-k-$seed", + initialValue: rows[index].name, + hintText: "Add URL Parameter", + onChanged: (value) { + rows[index] = rows[index].copyWith(name: value); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + Text( + "=", + style: kCodeStyle, + ), + ), + DataCell( + CellField( + keyId: "$selectedId-$index-params-v-$seed", + initialValue: rows[index].value, + hintText: "Add Value", + onChanged: (value) { + rows[index] = rows[index].copyWith(value: value); + _onFieldChange(selectedId!); + }, + colorScheme: Theme.of(context).colorScheme, + ), + ), + DataCell( + InkWell( + child: Theme.of(context).brightness == Brightness.dark + ? kIconRemoveDark + : kIconRemoveLight, + onTap: () { + seed = random.nextInt(kRandMax); + if (rows.length == 1) { + setState(() { + rows = [ + kNameValueEmptyModel, + ]; + isRowEnabledList = [true]; + }); + } else { + rows.removeAt(index); + isRowEnabledList.removeAt(index); + } + _onFieldChange(selectedId!); + }, + ), + ), + ], + ); + }, + ); + return Stack( children: [ Container( @@ -90,88 +167,11 @@ class EditRequestURLParamsState extends ConsumerState { dividerThickness: 0, horizontalMargin: 0, headingRowHeight: 0, - dataRowHeight: kDataRowHeight, + dataRowHeight: kDataTableRowHeight, bottomMargin: kDataTableBottomPadding, isVerticalScrollBarVisible: true, columns: columns, - rows: List.generate( - rows.length, - (index) { - return DataRow( - key: ValueKey("$selectedId-$index-params-row-$seed"), - cells: [ - DataCell( - CheckBox( - keyId: "$selectedId-$index-params-c-$seed", - value: isRowEnabledList[index], - onChanged: (value) { - setState(() { - isRowEnabledList[index] = value!; - }); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ), - ), - DataCell( - CellField( - keyId: "$selectedId-$index-params-k-$seed", - initialValue: rows[index].name, - hintText: "Add URL Parameter", - onChanged: (value) { - rows[index] = - rows[index].copyWith(name: value); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ), - ), - DataCell( - Text( - "=", - style: kCodeStyle, - ), - ), - DataCell( - CellField( - keyId: "$selectedId-$index-params-v-$seed", - initialValue: rows[index].value, - hintText: "Add Value", - onChanged: (value) { - rows[index] = - rows[index].copyWith(value: value); - _onFieldChange(selectedId!); - }, - colorScheme: Theme.of(context).colorScheme, - ), - ), - DataCell( - InkWell( - child: Theme.of(context).brightness == - Brightness.dark - ? kIconRemoveDark - : kIconRemoveLight, - onTap: () { - seed = random.nextInt(kRandMax); - if (rows.length == 1) { - setState(() { - rows = [ - kNameValueEmptyModel, - ]; - isRowEnabledList = [true]; - }); - } else { - rows.removeAt(index); - isRowEnabledList.removeAt(index); - } - _onFieldChange(selectedId!); - }, - ), - ), - ], - ); - }, - ), + rows: dataRows, ), ), ), diff --git a/lib/widgets/form_data_field.dart b/lib/widgets/form_data_field.dart deleted file mode 100644 index 7b7751fb..00000000 --- a/lib/widgets/form_data_field.dart +++ /dev/null @@ -1,83 +0,0 @@ -import 'package:apidash/consts.dart'; -import 'package:flutter/material.dart'; -import 'dropdowns.dart'; - -class FormDataField extends StatefulWidget { - const FormDataField({ - super.key, - required this.keyId, - this.initialValue, - this.hintText, - this.onChanged, - this.colorScheme, - this.formDataType, - this.onFormDataTypeChanged, - }); - - final String keyId; - final String? initialValue; - final String? hintText; - final void Function(String)? onChanged; - final ColorScheme? colorScheme; - final FormDataType? formDataType; - final void Function(FormDataType?)? onFormDataTypeChanged; - - @override - State createState() => _FormDataFieldState(); -} - -class _FormDataFieldState extends State { - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var colorScheme = widget.colorScheme ?? Theme.of(context).colorScheme; - return Row( - children: [ - Expanded( - flex: 1, - child: TextFormField( - initialValue: widget.initialValue, - key: Key(widget.keyId), - style: kCodeStyle.copyWith( - color: colorScheme.onSurface, - ), - decoration: InputDecoration( - hintStyle: kCodeStyle.copyWith( - color: colorScheme.outline.withOpacity( - kHintOpacity, - ), - ), - hintText: widget.hintText, - contentPadding: const EdgeInsets.only(bottom: 12), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: colorScheme.primary.withOpacity( - kHintOpacity, - ), - ), - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: colorScheme.surfaceVariant, - ), - ), - suffixIcon: DropdownButtonFormData( - formDataType: widget.formDataType, - onChanged: (p0) { - if (widget.onFormDataTypeChanged != null) { - widget.onFormDataTypeChanged!(p0); - } - }, - ), - ), - onChanged: widget.onChanged, - ), - ), - ], - ); - } -} diff --git a/lib/widgets/widgets.dart b/lib/widgets/widgets.dart index bb54b3ff..0a4c8eaa 100644 --- a/lib/widgets/widgets.dart +++ b/lib/widgets/widgets.dart @@ -7,7 +7,6 @@ export 'dropdowns.dart'; export 'editor_json.dart'; export 'editor.dart'; export 'error_message.dart'; -export 'form_data_field.dart'; export 'headerfield.dart'; export 'intro_message.dart'; export 'json_previewer.dart'; diff --git a/test/widgets/form_data_field_test.dart b/test/widgets/form_data_field_test.dart deleted file mode 100644 index b5748370..00000000 --- a/test/widgets/form_data_field_test.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:apidash/widgets/form_data_field.dart'; - -void main() { - testWidgets('Testing for Form Data Widget', (tester) async { - await tester.pumpWidget( - const MaterialApp( - title: 'Form Data Field Widget', - home: Scaffold( - body: FormDataField( - keyId: "1", - initialValue: "Test Field", - ), - ), - ), - ); - - expect(find.text("Test Field"), findsOneWidget); - }); -} From f1ec852acb994b3e12c7a50c49d70b1d7bdcc250 Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Sun, 17 Mar 2024 05:39:54 +0100 Subject: [PATCH 014/138] Add test case for selectedIdEditStateProvider after rename button is tapped --- test/providers/ui_providers_test.dart | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index cc9b25c0..ee62131e 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -230,5 +230,35 @@ void main() { final container = ProviderScope.containerOf(collectionPane); expect(container.read(selectedIdEditStateProvider), null); }); + + testWidgets( + 'selectedIdEditStateProvider should not be null after rename button has been tapped', + (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: CollectionPane(), + ), + ), + ); + + // Tap on the three dots to open the request card menu + await tester.tap(find.byType(RequestList)); + await tester.pump(); + await tester.tap(find.byType(RequestItem)); + await tester.pump(); + await tester.tap(find.byIcon(Icons.more_vert).first); + await tester.pumpAndSettle(); + + // Tap on the "Rename" option in the menu + await tester.tap(find.text('Rename')); + await tester.pumpAndSettle(); + + // Verify that the selectedIdEditStateProvider is not null + final collectionPane = tester.element(find.byType(CollectionPane)); + final container = ProviderScope.containerOf(collectionPane); + expect(container.read(selectedIdEditStateProvider), isNotNull); + expect((container.read(selectedIdEditStateProvider)).runtimeType, String); + }); }); } From 1513cfe3c1447b72b35be69706c9f3e8c1d5f020 Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Sun, 17 Mar 2024 05:55:39 +0100 Subject: [PATCH 015/138] Add test case for when selectedIdEditStateProvider is reset --- test/providers/ui_providers_test.dart | 39 +++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index ee62131e..fb9056e1 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -260,5 +260,44 @@ void main() { expect(container.read(selectedIdEditStateProvider), isNotNull); expect((container.read(selectedIdEditStateProvider)).runtimeType, String); }); + + testWidgets( + 'It should be set back to null when user taps outside name editor', + (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: CollectionPane(), + ), + ), + ); + + // Grab the CollectionPane widget and its ProviderContainer + final collectionPane = tester.element(find.byType(CollectionPane)); + final container = ProviderScope.containerOf(collectionPane); + + // Tap on the three dots to open the request card menu + await tester.tap(find.byType(RequestList)); + await tester.pump(); + await tester.tap(find.byType(RequestItem)); + await tester.pump(); + await tester.tap(find.byIcon(Icons.more_vert).first); + await tester.pumpAndSettle(); + + // Tap on the "Rename" option in the menu + await tester.tap(find.text('Rename')); + await tester.pumpAndSettle(); + + // Verify that the selectedIdEditStateProvider is not null + expect(container.read(selectedIdEditStateProvider), isNotNull); + expect((container.read(selectedIdEditStateProvider)).runtimeType, String); + + // Tap on the screen to simulate tapping outside the name editor + await tester.tap(find.byType(CollectionPane)); + await tester.pumpAndSettle(); + + // Verify that the selectedIdEditStateProvider is null + expect(container.read(selectedIdEditStateProvider), null); + }); }); } From df25a1b1b366293ff67d52c91dfd9888ff85ef54 Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Sun, 17 Mar 2024 06:04:49 +0100 Subject: [PATCH 016/138] Add test case to verify proper disposal of selectedIdEditStateProvider --- test/providers/ui_providers_test.dart | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index fb9056e1..dde4983f 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -299,5 +299,35 @@ void main() { // Verify that the selectedIdEditStateProvider is null expect(container.read(selectedIdEditStateProvider), null); }); + testWidgets("It should be properly disposed", (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: CollectionPane(), + ), + ), + ); + + // Grab the Dashboard widget and its ProviderContainer + final collectionPane = tester.element(find.byType(CollectionPane)); + final container = ProviderScope.containerOf(collectionPane); + + // Pumping a different widget to remove the CollectionPane from the widget tree + await tester.pumpWidget( + const MaterialApp( + home: Scaffold(body: Text('Foo')), + ), + ); + + // Verify that the ProviderContainer has been disposed + // by trying to read from disposed container + bool isDisposed = false; + try { + container.read(selectedIdEditStateProvider); + } catch (e) { + isDisposed = true; + } + expect(isDisposed, true); + }); }); } From 41ae457510a3deb7eec44a2d5e2c0e2b026b5f32 Mon Sep 17 00:00:00 2001 From: Shruti Roy Date: Sun, 17 Mar 2024 23:19:52 +0530 Subject: [PATCH 017/138] created php curl codegen file --- lib/codegen/php/curl.dart | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 lib/codegen/php/curl.dart diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart new file mode 100644 index 00000000..6b5239fb --- /dev/null +++ b/lib/codegen/php/curl.dart @@ -0,0 +1,9 @@ +import 'dart:convert'; +import 'package:jinja/jinja.dart' as jj; +import 'package:apidash/utils/utils.dart' + show getNewUuid, getValidRequestUri, requestModelToHARJsonRequest; +import 'package:apidash/models/models.dart' show RequestModel; +import 'package:apidash/consts.dart'; + +class PHPcURLCodeGen { +} From 1c288bc7c24f3b32cd8c87cc2d8259849821f423 Mon Sep 17 00:00:00 2001 From: Shruti Roy Date: Sun, 17 Mar 2024 23:21:39 +0530 Subject: [PATCH 018/138] added http verb to php curlopt conversion function --- lib/codegen/php/curl.dart | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index 6b5239fb..cd62e405 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -6,4 +6,23 @@ import 'package:apidash/models/models.dart' show RequestModel; import 'package:apidash/consts.dart'; class PHPcURLCodeGen { + //function for http verb to curl mapping + String httpMethod(String methodName) { + switch (methodName) { + case "POST": + return "CURLOPT_POST"; + case "GET": + return "CURLOPT_HTTPGET"; + case "PUT": + return "CURLOPT_PUT"; + case "DELETE": + return "CURLOPT_CUSTOMREQUEST"; + case "PATCH": + return "CURLOPT_CUSTOMREQUEST"; + case "HEAD": + return "CURLOPT_NOBODY"; + default: + return ""; + } + } } From 69ec62acacfcbeae83ad3dae9d1d1996df2e0eae Mon Sep 17 00:00:00 2001 From: Shruti Roy Date: Sun, 17 Mar 2024 23:24:18 +0530 Subject: [PATCH 019/138] added basic templates for rendering --- lib/codegen/php/curl.dart | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index cd62e405..dd804028 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -6,6 +6,28 @@ import 'package:apidash/models/models.dart' show RequestModel; import 'package:apidash/consts.dart'; class PHPcURLCodeGen { + //starting template + final String kTemplateStart = """ + Date: Sun, 17 Mar 2024 23:26:24 +0530 Subject: [PATCH 020/138] added further basic templates for headers and request creation --- lib/codegen/php/curl.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index dd804028..11d3ee79 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -16,6 +16,22 @@ class PHPcURLCodeGen { \$request = curl_init(\$uri); +"""; + + //specifying headers + String kTemplateHeaders = """ + +\$headers = [{{headers}}]; +curl_setopt(\$request, CURLOPT_HTTPHEADER, \$headers); + +"""; + + //request template + String kTemplateRequest = """ + +curl_setopt(\$request, CURLOPT_RETURNTRANSFER, 1); +curl_setopt(\$request, {{method}}, 1); + """; From b0556da2358c2aea737240f29bcc072e1f3074af Mon Sep 17 00:00:00 2001 From: Shruti Roy Date: Sun, 17 Mar 2024 23:27:03 +0530 Subject: [PATCH 021/138] added uri template --- lib/codegen/php/curl.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index 11d3ee79..1e08a240 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -11,6 +11,12 @@ class PHPcURLCodeGen { Date: Sun, 17 Mar 2024 23:27:28 +0530 Subject: [PATCH 022/138] added template for query parameters --- lib/codegen/php/curl.dart | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index 1e08a240..d3053357 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -15,6 +15,17 @@ class PHPcURLCodeGen { final String kTemplateUri = """ \$uri = "{{uri}}"; +"""; + + //defining query parameters + String kTemplateParams = """ + +\$queryParams = [{{params}}]; +\$queryString = "?" . http_build_query(\$queryParams); +if (count(\$queryParams) > 0) { + \$uri .= \$queryString; +} + """; //initialising the request From dc2bb203fe6bd0381a90407227ade7a0a712dafe Mon Sep 17 00:00:00 2001 From: Shruti Roy Date: Sun, 17 Mar 2024 23:39:33 +0530 Subject: [PATCH 023/138] added body rendering templates request body will be different based on whether or not the request contains files --- lib/codegen/php/curl.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index d3053357..f8e6f492 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -61,6 +61,18 @@ var_dump(\$response); """; + // + String kMultiPartBodyWithFiles = """ +\$request_body = build_data_files(\$boundary, \$fields, \$files); + +"""; + + // + String kMultiPartBodyWithoutFiles = """ +\$request_body = build_data(\$boundary, \$fields); + +"""; + //function for http verb to curl mapping String httpMethod(String methodName) { switch (methodName) { From d253f62f01e4a114b99cfb139b2b3a00d4c5275b Mon Sep 17 00:00:00 2001 From: Shruti Roy Date: Sun, 17 Mar 2024 23:49:48 +0530 Subject: [PATCH 024/138] added template for user defined class File - a constructor which takes a human readable name and the file and internally stores the contents of the file - if the file does not exist, then file_get_contents function returns false, in that case the contents of the file is an empty string --- lib/codegen/php/curl.dart | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index f8e6f492..8fba16b3 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -58,6 +58,29 @@ curl_setopt(\$request, {{method}}, 1); curl_close(\$request); var_dump(\$response); +"""; + + String kFileClassString = """ +class File +{ + public string \$name; + public string \$filename; + public string \$content; + + function __construct(\$name, \$filename) + { + \$this->name = \$name; + \$this->filename = \$filename; + \$available_content = file_get_contents(\$this->filename); + \$this->content = \$available_content ? \$available_content : ""; + } +} + + +"""; + +} + """; From 342fd78b5ffb3190f545e1d961f4c4b687baf497 Mon Sep 17 00:00:00 2001 From: Shruti Roy Date: Sun, 17 Mar 2024 23:55:48 +0530 Subject: [PATCH 025/138] added template for uuid and file boundary --- lib/codegen/php/curl.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index 8fba16b3..494cc0ff 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -60,6 +60,13 @@ var_dump(\$response); """; + //template for generating unique boundary + String kBoundaryUniqueIdTemplate = """ +\$boundary = "{{uuid}}"; + +"""; + + // String kFileClassString = """ class File { From 53179f88e243d4bfe2a3c796c46da0a58f92c0e1 Mon Sep 17 00:00:00 2001 From: Shruti Roy Date: Sun, 17 Mar 2024 23:57:56 +0530 Subject: [PATCH 026/138] added some more templates and functions - added template for request body which takes either a string build with form data or the json or text input given as it - added template for setting content type in header for multipart/form-data file format - passing the request-body in setopt method to set the request body - added functions to build formdata with or without a File --- lib/codegen/php/curl.dart | 65 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index 494cc0ff..95256e8c 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -35,6 +35,13 @@ if (count(\$queryParams) > 0) { """; + String kTemplateBody = """ + +\$request_body = << \$content) { + \$data .= "--" . \$delimiter . \$eol + . 'Content-Disposition: form-data; name="' . \$name . "\\"" . \$eol . \$eol + . \$content . \$eol; + } + \$data .= "--" . \$delimiter . "--" . \$eol; + return \$data; +} +"""; + + //function to build formdata with 'file' type + String kBuildFormDataFunctionWithFilesString = """ +function build_data_files(\$boundary, \$fields, \$files) +{ + \$data = ''; + \$eol = "\\r\\n"; + + \$delimiter = '-------------' . \$boundary; + + foreach (\$fields as \$name => \$content) { + \$data .= "--" . \$delimiter . \$eol + . 'Content-Disposition: form-data; name="' . \$name . "\\"" . \$eol . \$eol + . \$content . \$eol; + } + + foreach (\$files as \$uploaded_file) { + if (\$uploaded_file instanceof File) { + \$data .= "--" . \$delimiter . \$eol + . 'Content-Disposition: form-data; name="' . \$uploaded_file->name . '"; filename="' . \$uploaded_file->filename . '"' . \$eol + . 'Content-Transfer-Encoding: binary' . \$eol; + + \$data .= \$eol; + \$data .= \$uploaded_file->content . \$eol; + } + } + \$data .= "--" . \$delimiter . "--" . \$eol; + + + return \$data; } """; - // String kMultiPartBodyWithFiles = """ \$request_body = build_data_files(\$boundary, \$fields, \$files); From ced49940915884edb266bfbd18a6db330fd68a4c Mon Sep 17 00:00:00 2001 From: Shruti Roy Date: Mon, 18 Mar 2024 00:10:33 +0530 Subject: [PATCH 027/138] added get code function to generate php curl code --- lib/codegen/php/curl.dart | 167 +++++++++++++++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 1 deletion(-) diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index 95256e8c..179b2100 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -6,7 +6,6 @@ import 'package:apidash/models/models.dart' show RequestModel; import 'package:apidash/consts.dart'; class PHPcURLCodeGen { - //starting template final String kTemplateStart = """ queryList = []; + for (MapEntry entry in params.entries) { + String entryStr = "\"${entry.key}\" => \"${entry.value}\""; + queryList.add(entryStr); + } + String paramsString = "\n ${queryList.join(",\n ")}\n"; + + result += templateParams.render({"params": paramsString}); + } + } + + // renders the initial request init function call + var templateRequestInit = jj.Template(kTemplateRequestInit); + result += templateRequestInit.render(); + + var harJson = + requestModelToHARJsonRequest(requestModel, useEnabled: true); + + var headers = harJson["headers"]; + + //parses and adds the headers + if (headers.isNotEmpty || requestModel.hasFormData) { + var templateHeader = jj.Template(kTemplateHeaders); + var m = {}; + for (var i in headers) { + m[i["name"]] = i["value"]; + } + + if (requestModel.hasFormData) { + // we will override any existing boundary and use our own boundary + m['Content-Type'] = + "multipart/form-data; boundary=-------------$uuid"; + + var boundaryUniqueIdTemplate = + jj.Template(kBoundaryUniqueIdTemplate); + result += boundaryUniqueIdTemplate.render({"uuid": uuid}); + + var fieldsString = '\$fields = [\n'; + var filesString = '\$files = [\n'; + + for (var formData in requestModel.formDataMapList) { + if (formData['type'] == 'text') { + // the four spaces on the left hand side are for indentation, hence do not remove + fieldsString += + ' "${formData['name']}" => "${formData['value']}",\n'; + } else if (formData['type'] == 'file') { + filesString += + ' new File("${formData['name']}", "${formData['value']}"),\n'; + } + } + + fieldsString += '];\n'; + filesString += '];\n'; + + result += fieldsString; + if (requestModel.hasFileInFormData) { + result += filesString; + + result += kMultiPartBodyWithFiles; + } else { + result += kMultiPartBodyWithoutFiles; + } + } + + var headersString = '\n'; + m.forEach((key, value) { + headersString += "\t\t\t\t'$key: $value', \n"; + }); + + result += templateHeader.render({ + "headers": headersString, + }); + } + + // contains the HTTP method associated with the request + var method = requestModel.method; + + // contains the entire request body as a string if body is present + var requestBody = requestModel.requestBody; + + //renders the request body + if (kMethodsWithBody.contains(method) && requestBody != null) { + var contentLength = utf8.encode(requestBody).length; + if (contentLength > 0) { + hasBody = true; + var templateBody = jj.Template(kTemplateBody); + result += templateBody.render({"body": requestBody}); + } + } + + //renders the request temlate + var templateRequest = jj.Template(kTemplateRequest); + result += templateRequest.render({ + "authority": uri.authority, + "method": httpMethod(method.name.toUpperCase()), + "path": uri.path, + "queryParamsStr": hasQuery ? "queryParamsStr" : "", + }); + + if (hasBody || requestModel.hasFormData) { + result += kStringRequestBody; + } + + //and of the request + result += kStringRequestEnd; + } + return result; + } catch (e) { + return null; + } + } + //function for http verb to curl mapping String httpMethod(String methodName) { switch (methodName) { From 7c1a94fe4c3098eb7bfc61fd30257e4755df4de5 Mon Sep 17 00:00:00 2001 From: Shruti Roy Date: Mon, 18 Mar 2024 00:12:02 +0530 Subject: [PATCH 028/138] added php curl in the language options --- lib/consts.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/consts.dart b/lib/consts.dart index e3d2dc6b..87746e55 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -281,7 +281,8 @@ enum CodegenLanguage { javaAsyncHttpClient("Java (asynchttpclient)", "java", "java"), javaHttpClient("Java (HttpClient)", "java", "java"), juliaHttp("Julia (HTTP)", "julia", "jl"), - phpGuzzle("PHP (guzzle)", "php", "php"); + phpGuzzle("PHP (guzzle)", "php", "php"), + phpCurl("PHP (curl)", "php", "php"); const CodegenLanguage(this.label, this.codeHighlightLang, this.ext); final String label; From e231df639749177045effd8197c3d9fbeb1db0f6 Mon Sep 17 00:00:00 2001 From: Shruti Roy Date: Mon, 18 Mar 2024 00:12:26 +0530 Subject: [PATCH 029/138] added code generation for php curl --- lib/codegen/codegen.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index 7c66b88f..9146efca 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -6,6 +6,7 @@ import 'dart/dio.dart'; import 'go/http.dart'; import 'kotlin/okhttp.dart'; import 'php/guzzle.dart'; +import 'php/curl.dart'; import 'python/http_client.dart'; import 'python/requests.dart'; import 'rust/actix.dart'; @@ -79,6 +80,8 @@ class Codegen { return RustUreqCodeGen().getCode(rM, boundary: boundary); case CodegenLanguage.phpGuzzle: return PhpGuzzleCodeGen().getCode(rM); + case CodegenLanguage.phpCurl: + return PHPcURLCodeGen().getCode(requestModel, defaultUriScheme); } } } From 98c2c46dd7bdf7f57ed71de30b701df313cc9beb Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Wed, 20 Mar 2024 10:13:56 +0200 Subject: [PATCH 030/138] add sendingTime var for Request Model class --- lib/models/request_model.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index 0ea6d735..3a04c0eb 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -31,6 +31,7 @@ class RequestModel { this.message, this.responseModel, this.isWorking = false, + this.sendingTime, }); final String id; @@ -50,6 +51,7 @@ class RequestModel { final String? message; final ResponseModel? responseModel; final bool isWorking; + final DateTime? sendingTime; List? get enabledRequestHeaders => getEnabledRows(requestHeaders, isHeaderEnabledList); @@ -133,6 +135,7 @@ class RequestModel { String? message, ResponseModel? responseModel, bool? isWorking, + DateTime? sendingTime, }) { var headers = requestHeaders ?? this.requestHeaders; var params = requestParams ?? this.requestParams; @@ -158,6 +161,7 @@ class RequestModel { message: message ?? this.message, responseModel: responseModel ?? this.responseModel, isWorking: isWorking ?? this.isWorking, + sendingTime: sendingTime ?? this.sendingTime, ); } From 99c8a002788e110e17e03fa3121c61567bc6329d Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Wed, 20 Mar 2024 10:14:30 +0200 Subject: [PATCH 031/138] Add timer for sending widget --- lib/providers/collection_providers.dart | 5 +- .../details_card/response_pane.dart | 7 +- lib/widgets/response_widgets.dart | 75 ++++++++++++++++--- 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index db6b7cf3..9946112f 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -180,7 +180,8 @@ class CollectionStateNotifier // set current model's isWorking to true and update state var map = {...state!}; - map[id] = requestModel.copyWith(isWorking: true); + map[id] = + requestModel.copyWith(isWorking: true, sendingTime: DateTime.now()); state = map; (http.Response?, Duration?, String?)? responseRec = await request( @@ -193,6 +194,7 @@ class CollectionStateNotifier responseStatus: -1, message: responseRec.$3, isWorking: false, + sendingTime: null, ); } else { final responseModel = baseResponseModel.fromResponse( @@ -205,6 +207,7 @@ class CollectionStateNotifier message: kResponseCodeReasons[statusCode], responseModel: responseModel, isWorking: false, + sendingTime: null, ); } diff --git a/lib/screens/home_page/editor_pane/details_card/response_pane.dart b/lib/screens/home_page/editor_pane/details_card/response_pane.dart index 703b873d..2cd0cbc9 100644 --- a/lib/screens/home_page/editor_pane/details_card/response_pane.dart +++ b/lib/screens/home_page/editor_pane/details_card/response_pane.dart @@ -12,12 +12,17 @@ class ResponsePane extends ConsumerWidget { final isWorking = ref.watch( selectedRequestModelProvider.select((value) => value?.isWorking)) ?? false; + final startSendingDate = ref.watch( + selectedRequestModelProvider.select((value) => value?.sendingTime)); final responseStatus = ref.watch( selectedRequestModelProvider.select((value) => value?.responseStatus)); final message = ref .watch(selectedRequestModelProvider.select((value) => value?.message)); + if (isWorking) { - return const SendingWidget(); + return SendingWidget( + startSendingTime: startSendingDate, + ); } if (responseStatus == null) { return const NotSentWidget(); diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index adf74985..66fbc083 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -1,3 +1,6 @@ +import 'dart:async'; + +import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:http_parser/http_parser.dart'; @@ -24,8 +27,10 @@ class NotSentWidget extends StatelessWidget { ), Text( 'Not Sent', - style: - Theme.of(context).textTheme.titleMedium?.copyWith(color: color), + style: Theme.of(context) + .textTheme + .titleMedium + ?.copyWith(color: color), ), ], ), @@ -33,17 +38,69 @@ class NotSentWidget extends StatelessWidget { } } -class SendingWidget extends StatelessWidget { - const SendingWidget({super.key}); +class SendingWidget extends StatefulWidget { + final DateTime? startSendingTime; + const SendingWidget({super.key, required this.startSendingTime}); + + @override + State createState() => _SendingWidgetState(); +} + +class _SendingWidgetState extends State { + int _millisecondsElapsed = 0; + Timer? _timer; + + @override + void initState() { + super.initState(); + if (widget.startSendingTime != null) { + _millisecondsElapsed = + DateTime.now().difference(widget.startSendingTime!).inMilliseconds; + _timer = Timer.periodic(const Duration(milliseconds: 10), _updateTimer); + } + } + + void _updateTimer(Timer timer) { + setState(() { + _millisecondsElapsed += 10; + }); + } + + @override + void dispose() { + if (_timer != null && _timer!.isActive) _timer?.cancel(); + super.dispose(); + } @override Widget build(BuildContext context) { return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Lottie.asset("assets/sending.json"), - ], + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Visibility( + visible: _millisecondsElapsed > 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.alarm), + const SizedBox( + width: 10, + ), + Text( + 'Time elapsed: ${humanizeDuration(Duration(milliseconds: _millisecondsElapsed))}', + textAlign: TextAlign.center, + overflow: TextOverflow.fade, + softWrap: false, + style: kTextStyleButton, + ), + ], + ), + ), + Lottie.asset("assets/sending.json"), + ], + ), ), ); } From fec18be44b826c17cec73edc22fc041d80f87721 Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Wed, 20 Mar 2024 10:15:06 +0200 Subject: [PATCH 032/138] unit testing for SendingWidget --- test/widgets/response_widgets_test.dart | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/widgets/response_widgets_test.dart b/test/widgets/response_widgets_test.dart index 7877a285..3bdd42a8 100644 --- a/test/widgets/response_widgets_test.dart +++ b/test/widgets/response_widgets_test.dart @@ -10,13 +10,31 @@ import 'package:apidash/models/models.dart'; import '../test_consts.dart'; void main() { - testWidgets('Testing Sending Widget', (tester) async { + testWidgets('Testing Sending Widget Without Timer', (tester) async { await tester.pumpWidget( MaterialApp( title: 'Send', theme: kThemeDataDark, home: const Scaffold( - body: SendingWidget(), + body: SendingWidget( + startSendingTime: null, + ), + ), + ), + ); + + expect(find.byType(Lottie), findsOneWidget); + }); + + testWidgets('Testing Sending Widget With Timer', (tester) async { + await tester.pumpWidget( + MaterialApp( + title: 'Send', + theme: kThemeDataDark, + home: Scaffold( + body: SendingWidget( + startSendingTime: DateTime.now(), + ), ), ), ); From f26ba583cc301d9ca60cce4e9a69af80672f048e Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Thu, 21 Mar 2024 00:32:20 +0200 Subject: [PATCH 033/138] update timer testing function --- lib/widgets/response_widgets.dart | 12 ++++++------ test/widgets/response_widgets_test.dart | 7 ++++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index 66fbc083..22e84a1e 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:http_parser/http_parser.dart'; @@ -40,7 +39,8 @@ class NotSentWidget extends StatelessWidget { class SendingWidget extends StatefulWidget { final DateTime? startSendingTime; - const SendingWidget({super.key, required this.startSendingTime}); + final bool isTest; + const SendingWidget({super.key, required this.startSendingTime, this.isTest=false}); @override State createState() => _SendingWidgetState(); @@ -54,15 +54,15 @@ class _SendingWidgetState extends State { void initState() { super.initState(); if (widget.startSendingTime != null) { - _millisecondsElapsed = + _millisecondsElapsed = widget.isTest ? 0 : DateTime.now().difference(widget.startSendingTime!).inMilliseconds; - _timer = Timer.periodic(const Duration(milliseconds: 10), _updateTimer); + _timer = Timer.periodic(const Duration(milliseconds: 100), _updateTimer); } } void _updateTimer(Timer timer) { setState(() { - _millisecondsElapsed += 10; + _millisecondsElapsed += 100; }); } @@ -80,7 +80,7 @@ class _SendingWidgetState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Visibility( - visible: _millisecondsElapsed > 0, + visible: _millisecondsElapsed >= 0, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ diff --git a/test/widgets/response_widgets_test.dart b/test/widgets/response_widgets_test.dart index 3bdd42a8..a8def9cc 100644 --- a/test/widgets/response_widgets_test.dart +++ b/test/widgets/response_widgets_test.dart @@ -34,12 +34,17 @@ void main() { home: Scaffold( body: SendingWidget( startSendingTime: DateTime.now(), + isTest: true, ), ), ), ); - + expect(find.text('Time elapsed: 0 ms'), findsOneWidget); expect(find.byType(Lottie), findsOneWidget); + + await tester.pump(const Duration(seconds: 1)); + + expect(find.text('Time elapsed: 1.00 s'), findsOneWidget); }); testWidgets('Testing Not Sent Widget', (tester) async { From 12ab5e0b99d7db784646cad7f5ee447c75bc4187 Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Thu, 21 Mar 2024 00:42:41 +0200 Subject: [PATCH 034/138] Renamed variable --- .../home_page/editor_pane/details_card/response_pane.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/home_page/editor_pane/details_card/response_pane.dart b/lib/screens/home_page/editor_pane/details_card/response_pane.dart index 2cd0cbc9..4a240932 100644 --- a/lib/screens/home_page/editor_pane/details_card/response_pane.dart +++ b/lib/screens/home_page/editor_pane/details_card/response_pane.dart @@ -12,7 +12,7 @@ class ResponsePane extends ConsumerWidget { final isWorking = ref.watch( selectedRequestModelProvider.select((value) => value?.isWorking)) ?? false; - final startSendingDate = ref.watch( + final startSendingTime = ref.watch( selectedRequestModelProvider.select((value) => value?.sendingTime)); final responseStatus = ref.watch( selectedRequestModelProvider.select((value) => value?.responseStatus)); @@ -21,7 +21,7 @@ class ResponsePane extends ConsumerWidget { if (isWorking) { return SendingWidget( - startSendingTime: startSendingDate, + startSendingTime: startSendingTime, ); } if (responseStatus == null) { From 83b3031a9a7370267e4a7f1426c162c77e67dfc5 Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Thu, 21 Mar 2024 00:45:25 +0200 Subject: [PATCH 035/138] Update collection_providers.dart --- lib/providers/collection_providers.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 9946112f..07e26822 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -194,7 +194,6 @@ class CollectionStateNotifier responseStatus: -1, message: responseRec.$3, isWorking: false, - sendingTime: null, ); } else { final responseModel = baseResponseModel.fromResponse( @@ -207,7 +206,6 @@ class CollectionStateNotifier message: kResponseCodeReasons[statusCode], responseModel: responseModel, isWorking: false, - sendingTime: null, ); } From de19fc427970db4f8bc283f69cc3de41fc727dcf Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Thu, 21 Mar 2024 00:04:45 +0100 Subject: [PATCH 036/138] Test initial value of sentRequestIdStateProvider --- test/providers/ui_providers_test.dart | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index dde4983f..c7a2f5a0 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -330,4 +330,23 @@ void main() { expect(isDisposed, true); }); }); + + group("Testing sentRequestIdStateProvider", () { + testWidgets( + 'sentRequestIdStateProvider should have an initial value of null', + (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: CollectionPane(), + ), + ), + ); + + // Verify that the initial value is null + final collectionPane = tester.element(find.byType(CollectionPane)); + final container = ProviderScope.containerOf(collectionPane); + expect(container.read(sentRequestIdStateProvider), null); + }); + }); } From d2aee57ef173e5cf2f90c718f8a2efc674d6fd5c Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Thu, 21 Mar 2024 01:31:55 +0100 Subject: [PATCH 037/138] Remove test case for sentRequestIdStateProvider I removed test case for this provider because this provider does not exist in the repository anymore. With recent changes, it has been removed. --- test/providers/ui_providers_test.dart | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index c7a2f5a0..dde4983f 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -330,23 +330,4 @@ void main() { expect(isDisposed, true); }); }); - - group("Testing sentRequestIdStateProvider", () { - testWidgets( - 'sentRequestIdStateProvider should have an initial value of null', - (tester) async { - await tester.pumpWidget( - const ProviderScope( - child: MaterialApp( - home: CollectionPane(), - ), - ), - ); - - // Verify that the initial value is null - final collectionPane = tester.element(find.byType(CollectionPane)); - final container = ProviderScope.containerOf(collectionPane); - expect(container.read(sentRequestIdStateProvider), null); - }); - }); } From 1db26fa86fd1947895026929f8c9ba138dcbc426 Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Fri, 22 Mar 2024 00:41:44 +0200 Subject: [PATCH 038/138] use kAssetSendingLottie --- lib/widgets/response_widgets.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index 22e84a1e..a2f2183a 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -98,7 +98,7 @@ class _SendingWidgetState extends State { ], ), ), - Lottie.asset("assets/sending.json"), + Lottie.asset(kAssetSendingLottie), ], ), ), From 796b38c8e7b144095eeef7a923fd8e48ead0d562 Mon Sep 17 00:00:00 2001 From: DenserMeerkat Date: Fri, 22 Mar 2024 17:17:51 +0530 Subject: [PATCH 039/138] fix: prevent adding multiple empty rows --- .../request_pane/request_form_data.dart | 14 +++++++++++--- .../details_card/request_pane/request_headers.dart | 8 ++++++-- .../details_card/request_pane/request_params.dart | 8 ++++++-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart index b3d8f67c..fd00b020 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart @@ -18,6 +18,7 @@ class _FormDataBodyState extends ConsumerState { late int seed; final random = Random.secure(); late List formRows; + bool isAddingRow = false; @override void initState() { @@ -45,6 +46,7 @@ class _FormDataBodyState extends ConsumerState { ] : rF; formRows = isFormDataEmpty ? rows : rows + [kFormDataEmptyModel]; + isAddingRow = false; DaviModel daviModelRows = DaviModel( rows: formRows, @@ -64,7 +66,10 @@ class _FormDataBodyState extends ConsumerState { hintText: " Add Key", onChanged: (value) { formRows[idx] = formRows[idx].copyWith(name: value); - if (isLast) formRows.add(kFormDataEmptyModel); + if (isLast && !isAddingRow) { + isAddingRow = true; + formRows.add(kFormDataEmptyModel); + } _onFieldChange(selectedId!); }, colorScheme: Theme.of(context).colorScheme, @@ -75,7 +80,7 @@ class _FormDataBodyState extends ConsumerState { type: value ?? FormDataType.text, ); formRows[idx] = formRows[idx].copyWith(value: ""); - if (idx == formRows.length - 1 && hasChanged) { + if (isLast && hasChanged) { formRows.add(kFormDataEmptyModel); } setState(() {}); @@ -157,7 +162,10 @@ class _FormDataBodyState extends ConsumerState { hintText: " Add Value", onChanged: (value) { formRows[idx] = formRows[idx].copyWith(value: value); - if (isLast) formRows.add(kFormDataEmptyModel); + if (isLast && !isAddingRow) { + isAddingRow = true; + formRows.add(kFormDataEmptyModel); + } _onFieldChange(selectedId!); }, colorScheme: Theme.of(context).colorScheme, diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index e5b0df59..f473ec3f 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -19,6 +19,7 @@ class EditRequestHeadersState extends ConsumerState { final random = Random.secure(); late List headerRows; late List isRowEnabledList; + bool isAddingRow = false; @override void initState() { @@ -52,6 +53,7 @@ class EditRequestHeadersState extends ConsumerState { ref.read(selectedRequestModelProvider)?.isHeaderEnabledList ?? List.filled(rH?.length ?? 0, true, growable: true); isRowEnabledList.add(false); + isAddingRow = false; DaviModel model = DaviModel( rows: headerRows, @@ -90,7 +92,8 @@ class EditRequestHeadersState extends ConsumerState { hintText: "Add Header Name", onChanged: (value) { headerRows[idx] = headerRows[idx].copyWith(name: value); - if (isLast) { + if (isLast && !isAddingRow) { + isAddingRow = true; isRowEnabledList[idx] = true; headerRows.add(kNameValueEmptyModel); isRowEnabledList.add(false); @@ -123,7 +126,8 @@ class EditRequestHeadersState extends ConsumerState { hintText: " Add Header Value", onChanged: (value) { headerRows[idx] = headerRows[idx].copyWith(value: value); - if (isLast) { + if (isLast && !isAddingRow) { + isAddingRow = true; isRowEnabledList[idx] = true; headerRows.add(kNameValueEmptyModel); isRowEnabledList.add(false); diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index 319330ba..7002f8eb 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -20,6 +20,7 @@ class EditRequestURLParamsState extends ConsumerState { final random = Random.secure(); late List paramRows; late List isRowEnabledList; + bool isAddingRow = false; @override void initState() { @@ -52,6 +53,7 @@ class EditRequestURLParamsState extends ConsumerState { ref.read(selectedRequestModelProvider)?.isParamEnabledList ?? List.filled(rP?.length ?? 0, true, growable: true); isRowEnabledList.add(false); + isAddingRow = false; DaviModel model = DaviModel( rows: paramRows, @@ -90,7 +92,8 @@ class EditRequestURLParamsState extends ConsumerState { hintText: "Add URL Parameter", onChanged: (value) { paramRows[idx] = paramRows[idx].copyWith(name: value); - if (isLast) { + if (isLast && !isAddingRow) { + isAddingRow = true; isRowEnabledList[idx] = true; paramRows.add(kNameValueEmptyModel); isRowEnabledList.add(false); @@ -123,7 +126,8 @@ class EditRequestURLParamsState extends ConsumerState { hintText: "Add Value", onChanged: (value) { paramRows[idx] = paramRows[idx].copyWith(value: value); - if (isLast) { + if (isLast && !isAddingRow) { + isAddingRow = true; isRowEnabledList[idx] = true; paramRows.add(kNameValueEmptyModel); isRowEnabledList.add(false); From 459ab83eb2c993a0ceab399e5925d61eb5c21ae0 Mon Sep 17 00:00:00 2001 From: Sudhar08 <99385366+sudhar08@users.noreply.github.com> Date: Fri, 22 Mar 2024 21:27:39 +0530 Subject: [PATCH 040/138] feat: Add a search/filter for collection pane #305 This feature adds a search/filter functionality to the collection pane, allowing users to easily search for specific requests based on their names. Users can input search queries to filter the requests displayed in the collection pane, improving the navigation and organization of requests within the application. --- lib/providers/collection_providers.dart | 35 +++++++++++++++++++++- lib/screens/home_page/collection_pane.dart | 34 ++++++++++++++++++--- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index db6b7cf3..30801ecb 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -1,3 +1,4 @@ +import 'package:collection/collection.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'settings_providers.dart'; import 'ui_providers.dart'; @@ -8,6 +9,7 @@ import '../consts.dart'; import 'package:http/http.dart' as http; final selectedIdStateProvider = StateProvider((ref) => null); +final searchQueryProvider = StateProvider((ref) => ''); final selectedRequestModelProvider = StateProvider((ref) { final selectedId = ref.watch(selectedIdStateProvider); @@ -31,7 +33,7 @@ final StateNotifierProvider?> class CollectionStateNotifier extends StateNotifier?> { CollectionStateNotifier(this.ref, this.hiveHandler) : super(null) { - var status = loadData(); + var status = filterRequests(ref.read(searchQueryProvider.notifier).state); Future.microtask(() { if (status) { ref.read(requestSequenceProvider.notifier).state = [ @@ -248,6 +250,37 @@ class CollectionStateNotifier } } + bool filterRequests(String query) { + if (query.isEmpty) { + + loadData(); + return true; + } else { + // Filter requests based on the query + final filteredRequests = state?.values.where((request) => + request.name.toLowerCase().contains(query.toLowerCase())).toList(); + + + if (filteredRequests != null && filteredRequests.isNotEmpty) { + + Map requestMap = {}; + + for (var request in filteredRequests) { + requestMap[request.id] = request; + } + + state = requestMap; + + } else { + print("No matching requests found"); + } + + + + return false; + } + } + Future saveData() async { ref.read(saveDataStateProvider.notifier).state = true; final saveResponse = ref.read(settingsProvider).saveResponses; diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index fd0b518a..c44ed56e 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; @@ -66,10 +67,33 @@ class CollectionPane extends ConsumerWidget { style: kTextStyleButton, ), ), + ], ), ), - kVSpacer8, + kVSpacer10, + SizedBox( + height:30, + child:SearchBar( + + onChanged: (value){ + if(value.isNotEmpty){ + ref.read(searchQueryProvider.notifier).state = value; + ref.read(collectionStateNotifierProvider.notifier) + .filterRequests(value); + } + else{ + + } + + }, + hintText: "search", + leading: Icon(Icons.search), + textStyle: MaterialStateTextStyle.resolveWith((states) => TextStyle(fontSize: 15.0)), + elevation: MaterialStateProperty.all(2.0), + )), + kVSpacer10, + const Expanded( child: RequestList(), ), @@ -110,7 +134,7 @@ class _RequestListState extends ConsumerState { final alwaysShowCollectionPaneScrollbar = ref.watch(settingsProvider .select((value) => value.alwaysShowCollectionPaneScrollbar)); - return Scrollbar( + return requestItems.isNotEmpty?Scrollbar( controller: controller, thumbVisibility: alwaysShowCollectionPaneScrollbar ? true : null, radius: const Radius.circular(12), @@ -118,7 +142,7 @@ class _RequestListState extends ConsumerState { padding: kPr8CollectionPane, scrollController: controller, buildDefaultDragHandles: false, - itemCount: requestSequence.length, + itemCount: requestItems.length, onReorder: (int oldIndex, int newIndex) { if (oldIndex < newIndex) { newIndex -= 1; @@ -131,6 +155,8 @@ class _RequestListState extends ConsumerState { }, itemBuilder: (context, index) { var id = requestSequence[index]; + print(requestItems[id]!); + return ReorderableDragStartListener( key: ValueKey(id), index: index, @@ -144,7 +170,7 @@ class _RequestListState extends ConsumerState { ); }, ), - ); + ):Text("data"); } } From 19c8406d364b0675e3d46796017b4c6b814a2216 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sat, 23 Mar 2024 17:50:19 +0530 Subject: [PATCH 041/138] Fix for clearResponse --- lib/models/request_model.dart | 2 ++ lib/providers/collection_providers.dart | 1 + 2 files changed, 3 insertions(+) diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index 0ea6d735..acf6a3eb 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -95,6 +95,7 @@ class RequestModel { RequestModel duplicate({ required String id, String? name, + int? requestTabIndex, }) { return RequestModel( id: id, @@ -102,6 +103,7 @@ class RequestModel { url: url, name: name ?? "${this.name} (copy)", description: description, + requestTabIndex: requestTabIndex ?? 0, requestHeaders: requestHeaders != null ? [...requestHeaders!] : null, requestParams: requestParams != null ? [...requestParams!] : null, isHeaderEnabledList: diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index db6b7cf3..75e9d7c5 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -102,6 +102,7 @@ class CollectionStateNotifier final newModel = currentModel.duplicate( id: id, name: currentModel.name, + requestTabIndex: currentModel.requestTabIndex, ); var map = {...state!}; map[id] = newModel; From 0884a1405835ba3dc98000dfa7bec60b95a9e8b3 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sat, 23 Mar 2024 17:51:49 +0530 Subject: [PATCH 042/138] Code cleanup & Refactoring --- lib/consts.dart | 42 +++++++++- lib/screens/home_page/collection_pane.dart | 4 +- .../request_pane/request_form_data.dart | 18 ++-- .../request_pane/request_headers.dart | 12 +-- .../request_pane/request_params.dart | 12 +-- .../details_card/response_pane.dart | 3 - lib/widgets/buttons.dart | 15 ++-- lib/widgets/request_widgets.dart | 18 ++-- lib/widgets/response_widgets.dart | 83 +++++-------------- lib/widgets/tabs.dart | 10 ++- 10 files changed, 103 insertions(+), 114 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index 277f6956..2ad9d185 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -56,6 +56,7 @@ const kForegroundOpacity = 0.05; const kOverlayBackgroundOpacity = 0.5; const kTextStyleButton = TextStyle(fontWeight: FontWeight.bold); +const kTextStyleTab = TextStyle(fontSize: 14); const kTextStyleButtonSmall = TextStyle(fontSize: 12); const kFormDataButtonLabelTextStyle = TextStyle( fontSize: 12, @@ -71,9 +72,13 @@ const kP5 = EdgeInsets.all(5); const kP8 = EdgeInsets.all(8); const kPs8 = EdgeInsets.only(left: 8); const kPs2 = EdgeInsets.only(left: 2); +const kPe8 = EdgeInsets.only(right: 8.0); const kPh20v5 = EdgeInsets.symmetric(horizontal: 20, vertical: 5); const kPh20v10 = EdgeInsets.symmetric(horizontal: 20, vertical: 10); const kP10 = EdgeInsets.all(10); +const kPv8 = EdgeInsets.symmetric(vertical: 8); +const kPv2 = EdgeInsets.symmetric(vertical: 2); +const kPh2 = EdgeInsets.symmetric(horizontal: 2); const kPt24o8 = EdgeInsets.only(top: 24, left: 8.0, right: 8.0, bottom: 8.0); const kPt5o10 = EdgeInsets.only(left: 10.0, right: 10.0, top: 5.0, bottom: 10.0); @@ -105,8 +110,6 @@ const kPb10 = EdgeInsets.only( const kPb15 = EdgeInsets.only( bottom: 15, ); -const kPr8CollectionPane = EdgeInsets.only(right: 8.0); -const kpsV5 = EdgeInsets.symmetric(vertical: 2); const kHSpacer4 = SizedBox(width: 4); const kHSpacer5 = SizedBox(width: 5); const kHSpacer10 = SizedBox(width: 10); @@ -118,7 +121,7 @@ const kVSpacer20 = SizedBox(height: 20); const kVSpacer40 = SizedBox(height: 40); const kTabAnimationDuration = Duration(milliseconds: 200); -const kTabHeight = 45.0; +const kTabHeight = 32.0; const kHeaderHeight = 32.0; const kSegmentHeight = 24.0; const kTextButtonMinWidth = 44.0; @@ -537,3 +540,36 @@ const kLabelSave = "Save"; const kLabelDownload = "Download"; const kLabelSaving = "Saving"; const kLabelSaved = "Saved"; +// Request Pane +const kLabelRequest = "Request"; +const kLabelHideCode = "Hide Code"; +const kLabelViewCode = "View Code"; +const kLabelURLParams = "URL Params"; +const kLabelHeaders = "Headers"; +const kLabelBody = "Body"; +const kNameCheckbox = "Checkbox"; +const kNameURLParam = "URL Parameter"; +const kNameHeader = "Header Name"; +const kNameValue = "Value"; +const kNameField = "Field"; +const kHintAddURLParam = "Add URL Parameter"; +const kHintAddValue = "Add Value"; +const kHintAddName = "Add Name"; +const kHintAddFieldName = "Add Field Name"; +const kLabelAddParam = "Add Param"; +const kLabelAddHeader = "Add Header"; +const kLabelSelectFile = "Select File"; +const kLabelAddFormField = "Add Form Field"; +// Response Pane +const kLabelNotSent = "Not Sent"; +const kLabelResponse = "Response"; +const kLabelResponseBody = "Response Body"; +const kTooltipClearResponse = "Clear Response"; +const kHeaderRow = ["Header Name", "Header Value"]; +const kLabelRequestHeaders = "Request Headers"; +const kLabelResponseHeaders = "Response Headers"; +const kLabelItems = "items"; +const kMsgError = "Error: Response data does not exist."; +const kMsgNullBody = "Response body is missing (null)."; +const kMsgNoContent = "No content"; +const kMsgUnknowContentType = "Unknown Response Content-Type"; diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index fd0b518a..bdcd9b5f 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -26,7 +26,7 @@ class CollectionPane extends ConsumerWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Padding( - padding: kPr8CollectionPane, + padding: kPe8, child: Wrap( alignment: WrapAlignment.spaceBetween, children: [ @@ -115,7 +115,7 @@ class _RequestListState extends ConsumerState { thumbVisibility: alwaysShowCollectionPaneScrollbar ? true : null, radius: const Radius.circular(12), child: ReorderableListView.builder( - padding: kPr8CollectionPane, + padding: kPe8, scrollController: controller, buildDefaultDragHandles: false, itemCount: requestSequence.length, diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart index 61bf9d59..a6bafd6e 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart @@ -52,8 +52,8 @@ class _FormDataBodyState extends ConsumerState { rows: formRows, columns: [ DaviColumn( - cellPadding: kpsV5, - name: 'Key', + cellPadding: kPv2, + name: kNameField, grow: 4, cellBuilder: (_, row) { int idx = row.index; @@ -63,7 +63,7 @@ class _FormDataBodyState extends ConsumerState { child: FormDataField( keyId: "$selectedId-$idx-form-v-$seed", initialValue: formRows[idx].name, - hintText: " Add Key", + hintText: kHintAddFieldName, onChanged: (value) { formRows[idx] = formRows[idx].copyWith(name: value); if (isLast && !isAddingRow) { @@ -93,7 +93,7 @@ class _FormDataBodyState extends ConsumerState { ), DaviColumn( width: 40, - cellPadding: kpsV5, + cellPadding: kPv2, cellAlignment: Alignment.center, cellBuilder: (_, row) { return Text( @@ -103,9 +103,9 @@ class _FormDataBodyState extends ConsumerState { }, ), DaviColumn( - name: 'Value', + name: kNameValue, grow: 4, - cellPadding: kpsV5, + cellPadding: kPv2, cellBuilder: (_, row) { int idx = row.index; bool isLast = idx + 1 == formRows.length; @@ -145,7 +145,7 @@ class _FormDataBodyState extends ConsumerState { (formRows[idx].type == FormDataType.file && formRows[idx].value.isNotEmpty) ? formRows[idx].value.toString() - : "Select File", + : kLabelSelectFile, textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, style: kFormDataButtonLabelTextStyle, @@ -159,7 +159,7 @@ class _FormDataBodyState extends ConsumerState { : CellField( keyId: "$selectedId-$idx-form-v-$seed", initialValue: formRows[idx].value, - hintText: " Add Value", + hintText: kHintAddValue, onChanged: (value) { formRows[idx] = formRows[idx].copyWith(value: value); if (isLast && !isAddingRow) { @@ -231,7 +231,7 @@ class _FormDataBodyState extends ConsumerState { }, icon: const Icon(Icons.add), label: const Text( - "Add Form Data", + kLabelAddFormField, style: kTextStyleButton, ), ), diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 0e09702c..ee5c574c 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -59,7 +59,7 @@ class EditRequestHeadersState extends ConsumerState { rows: headerRows, columns: [ DaviColumn( - name: 'Checkbox', + name: kNameCheckbox, width: 30, cellBuilder: (_, row) { int idx = row.index; @@ -80,7 +80,7 @@ class EditRequestHeadersState extends ConsumerState { }, ), DaviColumn( - name: 'Header Name', + name: kNameHeader, width: 70, grow: 1, cellBuilder: (_, row) { @@ -89,7 +89,7 @@ class EditRequestHeadersState extends ConsumerState { return HeaderField( keyId: "$selectedId-$idx-headers-k-$seed", initialValue: headerRows[idx].name, - hintText: "Add Header Name", + hintText: kHintAddName, onChanged: (value) { headerRows[idx] = headerRows[idx].copyWith(name: value); if (isLast && !isAddingRow) { @@ -115,7 +115,7 @@ class EditRequestHeadersState extends ConsumerState { }, ), DaviColumn( - name: 'Header Value', + name: kNameValue, grow: 1, cellBuilder: (_, row) { int idx = row.index; @@ -123,7 +123,7 @@ class EditRequestHeadersState extends ConsumerState { return CellField( keyId: "$selectedId-$idx-headers-v-$seed", initialValue: headerRows[idx].value, - hintText: " Add Header Value", + hintText: kHintAddValue, onChanged: (value) { headerRows[idx] = headerRows[idx].copyWith(value: value); if (isLast && !isAddingRow) { @@ -202,7 +202,7 @@ class EditRequestHeadersState extends ConsumerState { }, icon: const Icon(Icons.add), label: const Text( - "Add Header", + kLabelAddHeader, style: kTextStyleButton, ), ), diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index 2e690f56..47dca1a6 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -59,7 +59,7 @@ class EditRequestURLParamsState extends ConsumerState { rows: paramRows, columns: [ DaviColumn( - name: 'Checkbox', + name: kNameCheckbox, width: 30, cellBuilder: (_, row) { int idx = row.index; @@ -80,7 +80,7 @@ class EditRequestURLParamsState extends ConsumerState { }, ), DaviColumn( - name: 'URL Parameter', + name: kNameURLParam, width: 70, grow: 1, cellBuilder: (_, row) { @@ -89,7 +89,7 @@ class EditRequestURLParamsState extends ConsumerState { return CellField( keyId: "$selectedId-$idx-params-k-$seed", initialValue: paramRows[idx].name, - hintText: "Add URL Parameter", + hintText: kHintAddURLParam, onChanged: (value) { paramRows[idx] = paramRows[idx].copyWith(name: value); if (isLast && !isAddingRow) { @@ -115,7 +115,7 @@ class EditRequestURLParamsState extends ConsumerState { }, ), DaviColumn( - name: 'Value', + name: kNameValue, grow: 1, cellBuilder: (_, row) { int idx = row.index; @@ -123,7 +123,7 @@ class EditRequestURLParamsState extends ConsumerState { return CellField( keyId: "$selectedId-$idx-params-v-$seed", initialValue: paramRows[idx].value, - hintText: "Add Value", + hintText: kHintAddValue, onChanged: (value) { paramRows[idx] = paramRows[idx].copyWith(value: value); if (isLast && !isAddingRow) { @@ -202,7 +202,7 @@ class EditRequestURLParamsState extends ConsumerState { }, icon: const Icon(Icons.add), label: const Text( - "Add Param", + kLabelAddParam, style: kTextStyleButton, ), ), diff --git a/lib/screens/home_page/editor_pane/details_card/response_pane.dart b/lib/screens/home_page/editor_pane/details_card/response_pane.dart index 703b873d..c1c770cf 100644 --- a/lib/screens/home_page/editor_pane/details_card/response_pane.dart +++ b/lib/screens/home_page/editor_pane/details_card/response_pane.dart @@ -34,7 +34,6 @@ class ResponseDetails extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - var sm = ScaffoldMessenger.of(context); final responseStatus = ref.watch( selectedRequestModelProvider.select((value) => value?.responseStatus)); final message = ref @@ -52,8 +51,6 @@ class ResponseDetails extends ConsumerWidget { ref .read(collectionStateNotifierProvider.notifier) .clearResponse(selectedRequest?.id); - sm.hideCurrentSnackBar(); - sm.showSnackBar(getSnackBar('Response cleared')); }, ), const Expanded( diff --git a/lib/widgets/buttons.dart b/lib/widgets/buttons.dart index f4280380..41bcddb9 100644 --- a/lib/widgets/buttons.dart +++ b/lib/widgets/buttons.dart @@ -246,15 +246,12 @@ class ClearResponseButton extends StatelessWidget { @override Widget build(BuildContext context) { - return Tooltip( - message: 'Clear response', - child: TextButton( - style: TextButton.styleFrom(minimumSize: const Size(40, 40)), - onPressed: onPressed, - child: const Icon( - Icons.delete, - size: 20, - ), + return IconButton( + tooltip: kTooltipClearResponse, + onPressed: onPressed, + icon: const Icon( + Icons.delete, + size: 16, ), ); } diff --git a/lib/widgets/request_widgets.dart b/lib/widgets/request_widgets.dart index ffac504e..7375a3b4 100644 --- a/lib/widgets/request_widgets.dart +++ b/lib/widgets/request_widgets.dart @@ -48,16 +48,12 @@ class _RequestPaneState extends State return Column( children: [ Padding( - padding: kPh20v10, + padding: kP8, child: SizedBox( height: kHeaderHeight, child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.end, children: [ - Text( - "Request", - style: Theme.of(context).textTheme.titleMedium, - ), FilledButton.tonalIcon( onPressed: widget.onPressedCodeButton, icon: Icon( @@ -68,7 +64,8 @@ class _RequestPaneState extends State label: SizedBox( width: 75, child: Text( - widget.codePaneVisible ? "Hide Code" : "View Code"), + widget.codePaneVisible ? kLabelHideCode : kLabelViewCode, + ), ), ), ], @@ -79,18 +76,19 @@ class _RequestPaneState extends State key: Key(widget.selectedId!), controller: _controller, overlayColor: kColorTransparentState, + labelPadding: kPh2, onTap: widget.onTapTabBar, tabs: [ TabLabel( - text: 'URL Params', + text: kLabelURLParams, showIndicator: widget.showIndicators[0], ), TabLabel( - text: 'Headers', + text: kLabelHeaders, showIndicator: widget.showIndicators[1], ), TabLabel( - text: 'Body', + text: kLabelBody, showIndicator: widget.showIndicators[2], ), ], diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index e641b03d..0b570c19 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -23,7 +23,7 @@ class NotSentWidget extends StatelessWidget { color: color, ), Text( - 'Not Sent', + kLabelNotSent, style: Theme.of(context).textTheme.titleMedium?.copyWith(color: color), ), @@ -66,42 +66,19 @@ class ResponsePaneHeader extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( - padding: kPh20v10, + padding: kPv8, child: SizedBox( height: kHeaderHeight, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text.rich( - TextSpan( - children: [ - const TextSpan( - text: "Response (", - ), - TextSpan( - text: "$responseStatus", - style: TextStyle( - color: getResponseStatusCodeColor( - responseStatus, - brightness: Theme.of(context).brightness, - ), - fontFamily: kCodeStyle.fontFamily, - ), - ), - const TextSpan( - text: ")", - ), - ], - style: Theme.of(context).textTheme.titleMedium, - ), - ), - kHSpacer20, + kHSpacer10, Expanded( child: Text( - message ?? "", + "$responseStatus: ${message ?? '-'}", softWrap: false, overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.titleMedium!.copyWith( + style: Theme.of(context).textTheme.bodyMedium?.copyWith( fontFamily: kCodeStyle.fontFamily, color: getResponseStatusCodeColor( responseStatus, @@ -110,10 +87,10 @@ class ResponsePaneHeader extends StatelessWidget { ), ), ), - kHSpacer20, + kHSpacer10, Text( humanizeDuration(time), - style: Theme.of(context).textTheme.titleMedium!.copyWith( + style: Theme.of(context).textTheme.bodyMedium?.copyWith( fontFamily: kCodeStyle.fontFamily, color: Theme.of(context).colorScheme.secondary, ), @@ -163,31 +140,15 @@ class _ResponseTabViewState extends State TabBar( key: Key(widget.selectedId!), controller: _controller, + labelPadding: kPh2, overlayColor: kColorTransparentState, onTap: (index) {}, tabs: const [ - SizedBox( - height: kTabHeight, - child: Center( - child: Text( - 'Body', - textAlign: TextAlign.center, - overflow: TextOverflow.fade, - softWrap: false, - style: kTextStyleButton, - ), - ), + TabLabel( + text: kLabelResponseBody, ), - SizedBox( - height: kTabHeight, - child: Center( - child: Text( - 'Headers', - textAlign: TextAlign.center, - overflow: TextOverflow.fade, - style: kTextStyleButton, - ), - ), + TabLabel( + text: kLabelHeaders, ), ], ), @@ -227,8 +188,8 @@ class ResponseHeadersHeader extends StatelessWidget { children: [ Expanded( child: Text( - "$name (${map.length} items)", - style: Theme.of(context).textTheme.labelLarge!.copyWith( + "$name (${map.length} $kLabelItems)", + style: Theme.of(context).textTheme.labelMedium?.copyWith( fontWeight: FontWeight.bold, ), ), @@ -243,8 +204,6 @@ class ResponseHeadersHeader extends StatelessWidget { } } -const kHeaderRow = ["Header Name", "Header Value"]; - class ResponseHeaders extends StatelessWidget { const ResponseHeaders({ super.key, @@ -263,7 +222,7 @@ class ResponseHeaders extends StatelessWidget { children: [ ResponseHeadersHeader( map: responseHeaders, - name: "Response Headers", + name: kLabelResponseHeaders, ), if (responseHeaders.isNotEmpty) kVSpacer5, if (responseHeaders.isNotEmpty) @@ -275,7 +234,7 @@ class ResponseHeaders extends StatelessWidget { kVSpacer10, ResponseHeadersHeader( map: requestHeaders, - name: "Request Headers", + name: kLabelRequestHeaders, ), if (requestHeaders.isNotEmpty) kVSpacer5, if (requestHeaders.isNotEmpty) @@ -302,20 +261,18 @@ class ResponseBody extends StatelessWidget { Widget build(BuildContext context) { final responseModel = selectedRequestModel?.responseModel; if (responseModel == null) { - return const ErrorMessage( - message: - 'Error: Response data does not exist. $kUnexpectedRaiseIssue'); + return const ErrorMessage(message: '$kMsgError $kUnexpectedRaiseIssue'); } var body = responseModel.body; var formattedBody = responseModel.formattedBody; if (body == null) { return const ErrorMessage( - message: 'Response body is missing (null). $kUnexpectedRaiseIssue'); + message: '$kMsgNullBody $kUnexpectedRaiseIssue'); } if (body.isEmpty) { return const ErrorMessage( - message: 'No content', + message: kMsgNoContent, showIcon: false, showIssueButton: false, ); @@ -325,7 +282,7 @@ class ResponseBody extends StatelessWidget { if (mediaType == null) { return ErrorMessage( message: - 'Unknown Response Content-Type - ${responseModel.contentType}. $kUnexpectedRaiseIssue'); + '$kMsgUnknowContentType - ${responseModel.contentType}. $kUnexpectedRaiseIssue'); } var responseBodyView = getResponseBodyViewOptions(mediaType); diff --git a/lib/widgets/tabs.dart b/lib/widgets/tabs.dart index eabf36c8..c2542a26 100644 --- a/lib/widgets/tabs.dart +++ b/lib/widgets/tabs.dart @@ -2,7 +2,11 @@ import 'package:flutter/material.dart'; import 'package:apidash/consts.dart'; class TabLabel extends StatelessWidget { - const TabLabel({super.key, required this.text, this.showIndicator = false}); + const TabLabel({ + super.key, + required this.text, + this.showIndicator = false, + }); final String text; final bool showIndicator; @@ -18,14 +22,14 @@ class TabLabel extends StatelessWidget { textAlign: TextAlign.center, overflow: TextOverflow.fade, softWrap: false, - style: kTextStyleButton, + style: kTextStyleTab, ), ), if (showIndicator) const Align( alignment: Alignment.topCenter, child: Padding( - padding: EdgeInsets.only(top: 6), + padding: EdgeInsets.only(top: 1), child: Icon( Icons.circle, size: 6, From 345f71a7c05b6f1a221f7ff4902e13f79d16035f Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sat, 23 Mar 2024 18:05:20 +0530 Subject: [PATCH 043/138] Fix tests --- test/widgets/request_widgets_test.dart | 4 ---- test/widgets/response_widgets_test.dart | 9 +++------ 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/test/widgets/request_widgets_test.dart b/test/widgets/request_widgets_test.dart index b50a033f..b47114b8 100644 --- a/test/widgets/request_widgets_test.dart +++ b/test/widgets/request_widgets_test.dart @@ -21,7 +21,6 @@ void main() { ); expect(find.byType(Center), findsAtLeastNWidgets(1)); - expect(find.text('Request'), findsOneWidget); expect(find.text('Hide Code'), findsOneWidget); expect(find.text('View Code'), findsNothing); expect(find.text('URL Params'), findsOneWidget); @@ -52,7 +51,6 @@ void main() { ); expect(find.byType(Center), findsAtLeastNWidgets(1)); - expect(find.text('Request'), findsOneWidget); expect(find.text('Hide Code'), findsOneWidget); expect(find.text('View Code'), findsNothing); expect(find.text('URL Params'), findsOneWidget); @@ -83,7 +81,6 @@ void main() { ); expect(find.byType(Center), findsAtLeastNWidgets(1)); - expect(find.text('Request'), findsOneWidget); expect(find.text('Hide Code'), findsNothing); expect(find.text('View Code'), findsOneWidget); expect(find.text('URL Params'), findsOneWidget); @@ -117,7 +114,6 @@ void main() { ); expect(find.byType(Center), findsAtLeastNWidgets(1)); - expect(find.text('Request'), findsOneWidget); expect(find.text('URL Params'), findsOneWidget); expect(find.text('Headers'), findsOneWidget); expect(find.text('Body'), findsOneWidget); diff --git a/test/widgets/response_widgets_test.dart b/test/widgets/response_widgets_test.dart index 7877a285..f6f3ecdd 100644 --- a/test/widgets/response_widgets_test.dart +++ b/test/widgets/response_widgets_test.dart @@ -52,11 +52,8 @@ void main() { ), ); - expect(find.byType(RichText), findsAtLeastNWidgets(1)); - expect( - find.textContaining("Response (", findRichText: true), findsOneWidget); - expect(find.text('Hi'), findsOneWidget); expect(find.textContaining("200", findRichText: true), findsOneWidget); + expect(find.textContaining("Hi", findRichText: true), findsOneWidget); expect(find.text(humanizeDuration(const Duration(microseconds: 23))), findsOneWidget); }); @@ -73,7 +70,7 @@ void main() { ), ); - expect(find.text('Body'), findsOneWidget); + expect(find.text('Response Body'), findsOneWidget); expect(find.text('Headers'), findsOneWidget); await tester.tap(find.text('Headers')); @@ -81,7 +78,7 @@ void main() { expect(find.text('first'), findsNothing); expect(find.text('second'), findsOneWidget); - await tester.tap(find.text('Body')); + await tester.tap(find.text('Response Body')); await tester.pumpAndSettle(); expect(find.text('first'), findsOneWidget); From 0cdca5feb0e273afdee453caae12e0a5f2c2a867 Mon Sep 17 00:00:00 2001 From: Tilakraj-B Date: Fri, 22 Mar 2024 00:36:53 +0530 Subject: [PATCH 044/138] main C# template, params template completed --- lib/codegen/codegen.dart | 3 + lib/codegen/csharp/rest_sharp.dart | 97 ++++++++++++++++++++++++++++++ lib/consts.dart | 3 +- lib/utils/http_utils.dart | 10 +++ 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 lib/codegen/csharp/rest_sharp.dart diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index f3f606ae..a4cd7331 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -1,6 +1,7 @@ import 'package:apidash/models/models.dart' show RequestModel; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' show getNewUuid; +import 'csharp/rest_sharp.dart'; import 'dart/http.dart'; import 'dart/dio.dart'; import 'go/http.dart'; @@ -82,6 +83,8 @@ class Codegen { return RustUreqCodeGen().getCode(rM, boundary: boundary); case CodegenLanguage.phpGuzzle: return PhpGuzzleCodeGen().getCode(rM); + case CodegenLanguage.cSharpRestSharp: + return CSharpRestSharp().getCode(rM); } } } diff --git a/lib/codegen/csharp/rest_sharp.dart b/lib/codegen/csharp/rest_sharp.dart new file mode 100644 index 00000000..53668809 --- /dev/null +++ b/lib/codegen/csharp/rest_sharp.dart @@ -0,0 +1,97 @@ +import 'package:jinja/jinja.dart' as jj; +import '../../models/request_model.dart'; +import '../../utils/har_utils.dart'; +import '../../utils/http_utils.dart'; + +class CSharpRestSharp { + String kStringLineBreak = """ + + +"""; + String kStringImports = """ +using System; +using RestSharp; +using System.Threading.Tasks; +"""; + + String kStringInit = """ +class Program +{ + static async Task Main(){ + try{ +"""; + + String kInitClientTemplate = """ + const String _baseUrl = "{{baseUrl}}"; + var client = new RestClient(_baseUrl); +"""; + + String kMethodTypeTemplate = """ + var request = new RestRequest("{{path}}", Method.{{method}}); +"""; + + String kTemplateParams = """ + request.AddParameter("{{param}}", "{{value}}"); +"""; + + String kStringEnd = """ + var response = await client.ExecuteAsync(request); + Console.WriteLine(response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + + String? getCode(RequestModel requestModel) { + try { + var harJson = + requestModelToHARJsonRequest(requestModel, useEnabled: true); + + String result = ""; + jj.Template kNodejsImportTemplate = jj.Template(kStringImports); + String importsData = kNodejsImportTemplate.render(); + result += importsData; + result += kStringLineBreak; + + result += kStringInit; + + jj.Template templateInitClient = jj.Template(kInitClientTemplate); + String initClient = + templateInitClient.render({"baseUrl": getBaseUrl(requestModel.url)}); + result += initClient; + result += kStringLineBreak; + + jj.Template templateMethodType = jj.Template(kMethodTypeTemplate); + String methodType = templateMethodType.render({ + "path": getUrlPath(requestModel.url), + "method": requestModel.method.name.replaceRange( + 0, + 1, + requestModel.method.name[0] + .toUpperCase()) // making the first character capital + }); + result += methodType; + result += kStringLineBreak; + + var params = harJson["queryString"]; + if (params.isNotEmpty) { + var templateParams = jj.Template(kTemplateParams); + String paramsResult = ""; + for (var query in params) { + paramsResult += templateParams + .render({"param": query["name"], "value": query["value"]}); + } + result += paramsResult; + result += kStringLineBreak; + } + + result += kStringEnd; + return result; + } catch (e) { + return null; + } + } +} diff --git a/lib/consts.dart b/lib/consts.dart index 2ad9d185..8b8c3b4a 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -297,7 +297,8 @@ enum CodegenLanguage { javaAsyncHttpClient("Java (asynchttpclient)", "java", "java"), javaHttpClient("Java (HttpClient)", "java", "java"), juliaHttp("Julia (HTTP)", "julia", "jl"), - phpGuzzle("PHP (guzzle)", "php", "php"); + phpGuzzle("PHP (guzzle)", "php", "php"), + cSharpRestSharp("C# (Rest Sharp)", "cs", "cs"); const CodegenLanguage(this.label, this.codeHighlightLang, this.ext); final String label; diff --git a/lib/utils/http_utils.dart b/lib/utils/http_utils.dart index 63aa6181..cdd8b87b 100644 --- a/lib/utils/http_utils.dart +++ b/lib/utils/http_utils.dart @@ -160,3 +160,13 @@ String? formatBody(String? body, MediaType? mediaType) { } return null; } + +String getBaseUrl(String url) { + Uri uri = Uri.parse(url); + return "${uri.scheme}://${uri.host}"; +} + +String getUrlPath(String url) { + Uri uri = Uri.parse(url); + return uri.path; +} From 1902cd39b2d0c9fa75a1ab62726de549e012841f Mon Sep 17 00:00:00 2001 From: Tilakraj-B Date: Fri, 22 Mar 2024 04:39:07 +0530 Subject: [PATCH 045/138] Template Completed --- lib/codegen/csharp/rest_sharp.dart | 72 +++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/lib/codegen/csharp/rest_sharp.dart b/lib/codegen/csharp/rest_sharp.dart index 53668809..29ecd7cf 100644 --- a/lib/codegen/csharp/rest_sharp.dart +++ b/lib/codegen/csharp/rest_sharp.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:jinja/jinja.dart' as jj; import '../../models/request_model.dart'; import '../../utils/har_utils.dart'; @@ -31,7 +33,22 @@ class Program """; String kTemplateParams = """ - request.AddParameter("{{param}}", "{{value}}"); + request.AddQueryParameter("{{param}}", "{{value}}"); +"""; + String kTemplateHeaders = """ + request.AddHeader("{{header}}", "{{value}}"); +"""; + String kTemplateFormData = """ + request.AddFile("{{name}}", "{{value}}"); + +"""; + String kTemplateJsonData = """ + var jsonBody = new {{jsonData}}; + request.AddJsonBody(jsonBody); +"""; + String kTemplateTextData = """ + var textBody = "{{textData}}"; + request.AddStringBody(textBody); """; String kStringEnd = """ @@ -78,7 +95,7 @@ class Program var params = harJson["queryString"]; if (params.isNotEmpty) { - var templateParams = jj.Template(kTemplateParams); + jj.Template templateParams = jj.Template(kTemplateParams); String paramsResult = ""; for (var query in params) { paramsResult += templateParams @@ -88,6 +105,57 @@ class Program result += kStringLineBreak; } + var headers = harJson["headers"]; + if (headers.isNotEmpty) { + jj.Template templateHeaders = jj.Template(kTemplateHeaders); + String headersResult = ""; + for (var header in headers) { + headersResult += templateHeaders + .render({"header": header["name"], "value": header["value"]}); + } + result += headersResult; + result += kStringLineBreak; + } + print(requestModel.formDataMapList); + print("hi"); + print(requestModel.formDataList); + if (requestModel.hasFormData) { + jj.Template templateFormData = jj.Template(kTemplateFormData); + String formDataResult = ""; + requestModel.formDataMapList.forEach((data) { + formDataResult += templateFormData.render({ + "name": data["name"], + "value": data["value"], + }); + }); + result += formDataResult; + result += kStringLineBreak; + } + + if (requestModel.hasJsonData) { + var templateJsonData = jj.Template(kTemplateJsonData); + Map bodyData = json.decode(requestModel.requestBody!); + String jsonDataResult = "{\n"; + + bodyData.forEach((key, value) { + jsonDataResult += "\t\t\t\t\t$key = \"$value\",\n"; + }); + jsonDataResult = jsonDataResult.length >= 3 + ? jsonDataResult.substring(0, jsonDataResult.length - 2) + : jsonDataResult; + jsonDataResult += "\n\t\t\t\t\t}"; + + result += templateJsonData.render({"jsonData": jsonDataResult}); + result += kStringLineBreak; + } + + if (requestModel.hasTextData) { + jj.Template templateTextData = jj.Template(kTemplateTextData); + result += + templateTextData.render({"textData": requestModel.requestBody}); + result += kStringLineBreak; + } + result += kStringEnd; return result; } catch (e) { From be39eade89d9bd99f0b71262796e59f6beacea5b Mon Sep 17 00:00:00 2001 From: Tilakraj-B Date: Sat, 23 Mar 2024 03:10:58 +0530 Subject: [PATCH 046/138] bugs fixed --- lib/codegen/csharp/rest_sharp.dart | 31 ++++++++++++++++++++---------- lib/utils/http_utils.dart | 2 +- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/codegen/csharp/rest_sharp.dart b/lib/codegen/csharp/rest_sharp.dart index 29ecd7cf..54ebb120 100644 --- a/lib/codegen/csharp/rest_sharp.dart +++ b/lib/codegen/csharp/rest_sharp.dart @@ -39,8 +39,12 @@ class Program request.AddHeader("{{header}}", "{{value}}"); """; String kTemplateFormData = """ - request.AddFile("{{name}}", "{{value}}"); - + {% if type == "text" -%} + request.AddParameter("{{name}}", "{{value}}", ParameterType.RequestBody); +{% else -%} + request.AddFile("{{name}}", "{{value}}"); +{% endif -%} + """; String kTemplateJsonData = """ var jsonBody = new {{jsonData}}; @@ -53,7 +57,8 @@ class Program String kStringEnd = """ var response = await client.ExecuteAsync(request); - Console.WriteLine(response.Content); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ Console.WriteLine("Error: " + ex); @@ -110,24 +115,30 @@ class Program jj.Template templateHeaders = jj.Template(kTemplateHeaders); String headersResult = ""; for (var header in headers) { - headersResult += templateHeaders - .render({"header": header["name"], "value": header["value"]}); + headersResult += templateHeaders.render({ + "header": header["name"], + "value": header["name"] == "Content-Type" + ? header["value"] + .toString() + .split(';') + .first // boundary is removed + : header["value"] + }); } result += headersResult; result += kStringLineBreak; } - print(requestModel.formDataMapList); - print("hi"); - print(requestModel.formDataList); + if (requestModel.hasFormData) { jj.Template templateFormData = jj.Template(kTemplateFormData); String formDataResult = ""; - requestModel.formDataMapList.forEach((data) { + for (var data in requestModel.formDataMapList) { formDataResult += templateFormData.render({ "name": data["name"], "value": data["value"], + "type": data["type"] }); - }); + } result += formDataResult; result += kStringLineBreak; } diff --git a/lib/utils/http_utils.dart b/lib/utils/http_utils.dart index cdd8b87b..1b86dfb1 100644 --- a/lib/utils/http_utils.dart +++ b/lib/utils/http_utils.dart @@ -163,7 +163,7 @@ String? formatBody(String? body, MediaType? mediaType) { String getBaseUrl(String url) { Uri uri = Uri.parse(url); - return "${uri.scheme}://${uri.host}"; + return "${uri.scheme}://${uri.host}${uri.hasPort ? ":${uri.port}" : ""}${uri.hasFragment ? "#${uri.fragment}" : ""}"; } String getUrlPath(String url) { From f5f833046b01f9ffe4769752a2e8ba22993d3b5e Mon Sep 17 00:00:00 2001 From: Tilakraj-B Date: Sat, 23 Mar 2024 17:19:40 +0530 Subject: [PATCH 047/138] added test for rest_sharp.dart and fixed minor bugs --- lib/codegen/csharp/rest_sharp.dart | 13 +- .../csharp_rest_sharp_codgen_test.dart | 976 ++++++++++++++++++ 2 files changed, 983 insertions(+), 6 deletions(-) create mode 100644 test/codegen/csharp_rest_sharp_codgen_test.dart diff --git a/lib/codegen/csharp/rest_sharp.dart b/lib/codegen/csharp/rest_sharp.dart index 54ebb120..c31a13a0 100644 --- a/lib/codegen/csharp/rest_sharp.dart +++ b/lib/codegen/csharp/rest_sharp.dart @@ -20,7 +20,7 @@ using System.Threading.Tasks; class Program { static async Task Main(){ - try{ + try{ """; String kInitClientTemplate = """ @@ -44,7 +44,6 @@ class Program {% else -%} request.AddFile("{{name}}", "{{value}}"); {% endif -%} - """; String kTemplateJsonData = """ var jsonBody = new {{jsonData}}; @@ -64,7 +63,7 @@ class Program Console.WriteLine("Error: " + ex); } } -} +} """; String? getCode(RequestModel requestModel) { @@ -105,8 +104,9 @@ class Program for (var query in params) { paramsResult += templateParams .render({"param": query["name"], "value": query["value"]}); + paramsResult += "\n"; } - result += paramsResult; + result += paramsResult.substring(0, paramsResult.length - 1); result += kStringLineBreak; } @@ -124,8 +124,9 @@ class Program .first // boundary is removed : header["value"] }); + headersResult += '\n'; } - result += headersResult; + result += headersResult.substring(0, headersResult.length - 1); result += kStringLineBreak; } @@ -139,7 +140,7 @@ class Program "type": data["type"] }); } - result += formDataResult; + result += formDataResult.substring(0, formDataResult.length - 1); result += kStringLineBreak; } diff --git a/test/codegen/csharp_rest_sharp_codgen_test.dart b/test/codegen/csharp_rest_sharp_codgen_test.dart new file mode 100644 index 00000000..e3d83628 --- /dev/null +++ b/test/codegen/csharp_rest_sharp_codgen_test.dart @@ -0,0 +1,976 @@ +import 'package:apidash/consts.dart'; +import 'package:apidash/screens/home_page/editor_pane/details_card/code_pane.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../request_models.dart'; + +void main() { + group("Get Request Test", () { + test("Get 1", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("", Method.Get); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet1, "https"), + expectedCode); + }); + + test("Get 2", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/country/data", Method.Get); + + request.AddQueryParameter("code", "US"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet2, "https"), + expectedCode); + }); + + test("Get 3", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/country/data", Method.Get); + + request.AddQueryParameter("code", "IND"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet3, "https"), + expectedCode); + }); + + test("Get 4", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/humanize/social", Method.Get); + + request.AddQueryParameter("num", "8700000"); + request.AddQueryParameter("digits", "3"); + request.AddQueryParameter("system", "SS"); + request.AddQueryParameter("add_space", "true"); + request.AddQueryParameter("trailing_zeros", "true"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet4, "https"), + expectedCode); + }); + + test("Get 5", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.github.com"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/repos/foss42/apidash", Method.Get); + + request.AddHeader("User-Agent", "Test Agent"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet5, "https"), + expectedCode); + }); + + test("Get 6", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.github.com"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/repos/foss42/apidash", Method.Get); + + request.AddQueryParameter("raw", "true"); + + request.AddHeader("User-Agent", "Test Agent"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet6, "https"), + expectedCode); + }); + + test("Get 7", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("", Method.Get); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet7, "https"), + expectedCode); + }); + + test("Get 8", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.github.com"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/repos/foss42/apidash", Method.Get); + + request.AddQueryParameter("raw", "true"); + + request.AddHeader("User-Agent", "Test Agent"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet8, "https"), + expectedCode); + }); + + test("Get 9", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/humanize/social", Method.Get); + + request.AddQueryParameter("num", "8700000"); + request.AddQueryParameter("add_space", "true"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet9, "https"), + expectedCode); + }); + + test("Get 10", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/humanize/social", Method.Get); + + request.AddHeader("User-Agent", "Test Agent"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet10, "https"), + expectedCode); + }); + + test("Get 11", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/humanize/social", Method.Get); + + request.AddQueryParameter("num", "8700000"); + request.AddQueryParameter("digits", "3"); + + request.AddHeader("User-Agent", "Test Agent"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet11, "https"), + expectedCode); + }); + + test("Get 12", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/humanize/social", Method.Get); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelGet12, "https"), + expectedCode); + }); + }); + + group("Head Request Test", () { + test("Head 1", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("", Method.Head); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelHead1, "https"), + expectedCode); + }); + + test("Head 2", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("", Method.Head); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelHead2, "https"), + expectedCode); + }); + }); + + group("Post Request Test", () { + test("Post 1", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/case/lower", Method.Post); + + request.AddHeader("Content-Type", "text/plain"); + + var textBody = "{ +"text": "I LOVE Flutter" +}"; + request.AddStringBody(textBody); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelPost1, "https"), + expectedCode); + }); + test("Post 2", () { + const expectedCode = """ +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/case/lower", Method.Post); + + request.AddHeader("Content-Type", "application/json"); + + var jsonBody = new { +\t\t\t\t\ttext = "I LOVE Flutter", +\t\t\t\t\tflag = "null", +\t\t\t\t\tmale = "true", +\t\t\t\t\tfemale = "false", +\t\t\t\t\tno = "1.2", +\t\t\t\t\tarr = "[null, true, false, null]" +\t\t\t\t\t}; + request.AddJsonBody(jsonBody); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelPost2, "https"), + expectedCode); + }); + test("Post 3", () { + const expectedCode = """ +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/case/lower", Method.Post); + + request.AddHeader("Content-Type", "application/json"); + request.AddHeader("User-Agent", "Test Agent"); + + var jsonBody = new { +\t\t\t\t\ttext = "I LOVE Flutter" +\t\t\t\t\t}; + request.AddJsonBody(jsonBody); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelPost3, "https"), + expectedCode); + }); + test("Post 4", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/io/form", Method.Post); + + request.AddHeader("Content-Type", "multipart/form-data"); + + request.AddParameter("text", "API", ParameterType.RequestBody); + request.AddParameter("sep", "|", ParameterType.RequestBody); + request.AddParameter("times", "3", ParameterType.RequestBody); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelPost4, "https"), + expectedCode); + }); + test("Post 5", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/io/form", Method.Post); + + request.AddHeader("Content-Type", "multipart/form-data"); + request.AddHeader("User-Agent", "Test Agent"); + + request.AddParameter("text", "API", ParameterType.RequestBody); + request.AddParameter("sep", "|", ParameterType.RequestBody); + request.AddParameter("times", "3", ParameterType.RequestBody); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelPost5, "https"), + expectedCode); + }); + test("Post 6", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/io/img", Method.Post); + + request.AddHeader("Content-Type", "multipart/form-data"); + + request.AddParameter("token", "xyz", ParameterType.RequestBody); + request.AddFile("imfile", "/Documents/up/1.png"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelPost6, "https"), + expectedCode); + }); + test("Post 7", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/io/img", Method.Post); + + request.AddHeader("Content-Type", "multipart/form-data"); + + request.AddParameter("token", "xyz", ParameterType.RequestBody); + request.AddFile("imfile", "/Documents/up/1.png"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelPost7, "https"), + expectedCode); + }); + test("Post 8", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/io/form", Method.Post); + + request.AddQueryParameter("size", "2"); + request.AddQueryParameter("len", "3"); + + request.AddHeader("Content-Type", "multipart/form-data"); + + request.AddParameter("text", "API", ParameterType.RequestBody); + request.AddParameter("sep", "|", ParameterType.RequestBody); + request.AddParameter("times", "3", ParameterType.RequestBody); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelPost8, "https"), + expectedCode); + }); + test("Post 9", () { + const expectedCode = r""" +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://api.apidash.dev"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/io/img", Method.Post); + + request.AddQueryParameter("size", "2"); + request.AddQueryParameter("len", "3"); + + request.AddHeader("Content-Type", "multipart/form-data"); + request.AddHeader("User-Agent", "Test Agent"); + request.AddHeader("Keep-Alive", "true"); + + request.AddParameter("token", "xyz", ParameterType.RequestBody); + request.AddFile("imfile", "/Documents/up/1.png"); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelPost9, "https"), + expectedCode); + }); + }); + + group("Put Request Test", () { + test("Put 1", () { + const expectedCode = """ +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://reqres.in"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/api/users/2", Method.Put); + + request.AddHeader("Content-Type", "application/json"); + + var jsonBody = new { +\t\t\t\t\tname = "morpheus", +\t\t\t\t\tjob = "zion resident" +\t\t\t\t\t}; + request.AddJsonBody(jsonBody); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelPut1, "https"), + expectedCode); + }); + }); + + group("Patch Request Test", () { + test("Patch 1", () { + const expectedCode = """ +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://reqres.in"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/api/users/2", Method.Patch); + + request.AddHeader("Content-Type", "application/json"); + + var jsonBody = new { +\t\t\t\t\tname = "marfeus", +\t\t\t\t\tjob = "accountant" +\t\t\t\t\t}; + request.AddJsonBody(jsonBody); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelPatch1, "https"), + expectedCode); + }); + }); + + group("Delete Request Test", () { + test("Delete 1", () { + const expectedCode = """ +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://reqres.in"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/api/users/2", Method.Delete); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelDelete1, "https"), + expectedCode); + }); + test("Delete 2", () { + const expectedCode = """ +using System; +using RestSharp; +using System.Threading.Tasks; + +class Program +{ + static async Task Main(){ + try{ + const String _baseUrl = "https://reqres.in"; + var client = new RestClient(_baseUrl); + + var request = new RestRequest("/api/users/2", Method.Delete); + + request.AddHeader("Content-Type", "application/json"); + + var jsonBody = new { +\t\t\t\t\tname = "marfeus", +\t\t\t\t\tjob = "accountant" +\t\t\t\t\t}; + request.AddJsonBody(jsonBody); + + var response = await client.ExecuteAsync(request); + Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Response Content: " + response.Content); + } + catch(Exception ex){ + Console.WriteLine("Error: " + ex); + } + } +} +"""; + expect( + codegen.getCode( + CodegenLanguage.cSharpRestSharp, requestModelDelete2, "https"), + expectedCode); + }); + }); +} From b8bd45a10ad1d3ec83c52951ac8016b5e7bf58f8 Mon Sep 17 00:00:00 2001 From: Apoorv Dwivedi Date: Sat, 23 Mar 2024 21:32:48 +0530 Subject: [PATCH 048/138] Fixed the java http client codegen --- lib/codegen/codegen.dart | 2 +- lib/codegen/java/httpclient.dart | 295 ++++++++++++++++--------------- 2 files changed, 157 insertions(+), 140 deletions(-) diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index f3f606ae..19b2a29a 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -60,7 +60,7 @@ class Codegen { case CodegenLanguage.javaAsyncHttpClient: return JavaAsyncHttpClientGen().getCode(rM); case CodegenLanguage.javaHttpClient: - return JavaHttpClientCodeGen().getCode(rM); + return JavaHttpClientCodeGen().getCode(rM, boundary: boundary); case CodegenLanguage.javaOkHttp: return JavaOkHttpCodeGen().getCode(rM); case CodegenLanguage.juliaHttp: diff --git a/lib/codegen/java/httpclient.dart b/lib/codegen/java/httpclient.dart index 037a9a87..e113fa10 100644 --- a/lib/codegen/java/httpclient.dart +++ b/lib/codegen/java/httpclient.dart @@ -1,183 +1,200 @@ -import 'dart:convert'; import 'package:jinja/jinja.dart' as jj; import 'package:apidash/utils/utils.dart' - show getValidRequestUri, requestModelToHARJsonRequest, stripUriParams; -import '../../models/request_model.dart'; + show getValidRequestUri, requestModelToHARJsonRequest; +import 'package:apidash/models/models.dart' show RequestModel; import 'package:apidash/consts.dart'; class JavaHttpClientCodeGen { - final String kTemplateStart = """ -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; + final String kTemplateStart = """import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.net.http.HttpHeaders; -import java.net.http.HttpRequest.BodyPublishers; -import java.net.http.HttpResponse.BodyHandlers; +import java.io.IOException; +{% if hasFormData %}import java.util.HashMap; +import java.util.Map; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList;{% endif %} +{% if hasJsonBody %}import com.google.gson.Gson; +import java.nio.charset.StandardCharsets;{% endif %} -public class JavaHttpClientExample { +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); - public static void main(String[] args) throws IOException, InterruptedException { - HttpClient client = HttpClient.newHttpClient(); -"""; - final String kTemplateUrl = ''' - - String url = "{{url}}"; - -'''; - - final String kTemplateUrlQuery = ''' - - String url = "{{url}}"; - try { - URI uri = new URI(url); - url = uri.resolve("{{params}}").toString(); - } catch (URISyntaxException e) { - e.printStackTrace(); - } - -'''; - - String kTemplateRequestBody = ''' - - String body = "{{body}}"; - -'''; - - final String kStringRequestStart = """ - - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(url)) """; - final String kTemplateRequestEnd = """ - .{{method}}({{body}}) - .build(); + String kTemplateUrl = """ + URI uri = URI.create("{{url}}"); - HttpResponse response = client.send(request, BodyHandlers.ofString()); - System.out.println(response.statusCode()); - System.out.println(response.body()); +"""; + + String kTemplateFormHeaderContentType = ''' +multipart/form-data; boundary={{boundary}}'''; + + String kTemplateMethod = """ +{% if method == 'get' %} + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); +{% elif method == 'post' %} + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST({% if hasBody %}bodyPublisher{% else %}HttpRequest.BodyPublishers.noBody(){% endif %}); +{% elif method == 'put' %} + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).PUT({% if hasBody %}bodyPublisher{% else %}HttpRequest.BodyPublishers.noBody(){% endif %}); +{% elif method == 'delete' %} + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("DELETE", {% if hasBody %}bodyPublisher{% else %}HttpRequest.BodyPublishers.noBody(){% endif %}); +{% elif method == 'patch' %} + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("PATCH", {% if hasBody %}bodyPublisher{% else %}HttpRequest.BodyPublishers.noBody(){% endif %}); +{% elif method == 'head' %} + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("HEAD", HttpRequest.BodyPublishers.noBody()); +{% endif %} +"""; + + String kTemplateRawBody = """ + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(\"\"\" + {{body}}\"\"\"); +"""; + + String kTemplateJsonBody = """ + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(\"\"\" +{{body}}\"\"\"), StandardCharsets.UTF_8); +"""; + + String kTemplateFormData = """ + String boundary = "{{boundary}}"; + Map data = new HashMap<>(); + {% for field in fields %} + {% if field.type == "file" %}data.put("{{field.name}}", Paths.get("{{field.value}}"));{% else %}data.put("{{field.name}}", "{{field.value}}");{% endif %}{% endfor %} + HttpRequest.BodyPublisher bodyPublisher = buildMultipartFormData(data, boundary); +"""; + + String kTemplateHeader = """ + requestBuilder = requestBuilder.headers({% for header, value in headers %} + "{{header}}", "{{value}}"{% if not loop.last %},{% endif %}{% endfor %} + ); + +"""; + + final String kTemplateEnd = """ + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); } + } + {% if hasFormData %} + private static HttpRequest.BodyPublisher buildMultipartFormData(Map data, String boundary) throws IOException { + var byteArrays = new ArrayList(); + var CRLF = "\\r\\n".getBytes(StandardCharsets.UTF_8); + + for (Map.Entry entry : data.entrySet()) { + byteArrays.add(("--" + boundary + "\\r\\n").getBytes(StandardCharsets.UTF_8)); + if (entry.getValue() instanceof Path) { + var file = (Path) entry.getValue(); + var fileName = file.getFileName().toString(); + byteArrays.add(("Content-Disposition: form-data; name=\\"" + entry.getKey() + "\\"; filename=\\"" + fileName + "\\"\\r\\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(("Content-Type: " + Files.probeContentType(file) + "\\r\\n\\r\\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(Files.readAllBytes(file)); + byteArrays.add(CRLF); + } else { + byteArrays.add(("Content-Disposition: form-data; name=\\"" + entry.getKey() + "\\"\\r\\n\\r\\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(entry.getValue().toString().getBytes(StandardCharsets.UTF_8)); + byteArrays.add(CRLF); + } + } + byteArrays.add(("--" + boundary + "--\\r\\n").getBytes(StandardCharsets.UTF_8)); + + return HttpRequest.BodyPublishers.ofByteArrays(byteArrays); + }{% endif %} } -\n """; String? getCode( - RequestModel requestModel, - ) { + RequestModel requestModel, { + String? boundary, + }) { try { String result = ""; - bool hasQuery = false; - bool hasBody = false; - bool hasJsonBody = false; + var requestBody = requestModel.requestBody; + String url = requestModel.url; + + result += jj.Template(kTemplateStart).render({ + "hasJsonBody": requestModel.hasJsonData, + "hasFormData": requestModel.hasFormData, + }); var rec = getValidRequestUri( - requestModel.url, + url, requestModel.enabledRequestParams, ); + Uri? uri = rec.$1; + var harJson = + requestModelToHARJsonRequest(requestModel, useEnabled: true); + if (uri != null) { - String url = stripUriParams(uri); + var templateUrl = jj.Template(kTemplateUrl); + result += templateUrl.render({"url": harJson["url"]}); - if (uri.hasQuery) { - var params = uri.queryParameters; - if (params.isNotEmpty) { - hasQuery = true; - var templateParams = jj.Template(kTemplateUrlQuery); - result += templateParams.render({"url": url, "params": uri.query}); - } + String? bodyPublisher = ""; + if (requestModel.hasTextData) { + var templateBody = jj.Template(kTemplateRawBody); + bodyPublisher = templateBody.render({"body": requestBody}); + } else if (requestModel.hasJsonData) { + var templateBody = jj.Template(kTemplateJsonBody); + bodyPublisher = templateBody.render({"body": requestBody}); + } else if (requestModel.hasFormData) { + var templateFormData = jj.Template(kTemplateFormData); + bodyPublisher = templateFormData.render({ + "fields": requestModel.formDataMapList, + "boundary": boundary, + }); } - if (!hasQuery) { - var templateUrl = jj.Template(kTemplateUrl); - result += templateUrl.render({"url": url}); - } - var rM = requestModel.copyWith(url: url); + result += bodyPublisher; - var harJson = requestModelToHARJsonRequest(rM, useEnabled: true); - - var method = requestModel.method; - var requestBody = requestModel.requestBody; - if (requestModel.hasFormData && - requestModel.formDataMapList.isNotEmpty && - kMethodsWithBody.contains(method)) { - var formDataList = requestModel.formDataMapList; - result += """ - StringBuilder formData = new StringBuilder(); - formData.append("""; - - for (var formDataMap in formDataList) { - result += '"""${formDataMap['name']}=${formDataMap['value']}&""",'; - } - - result = result.substring(0, result.length - 1); - result += ");\n"; - hasBody = true; - } else if (kMethodsWithBody.contains(method) && requestBody != null) { - var contentLength = utf8.encode(requestBody).length; - if (contentLength > 0) { - var templateBody = jj.Template(kTemplateRequestBody); - hasBody = true; - hasJsonBody = - requestBody.startsWith("{") && requestBody.endsWith("}"); - if (harJson["postData"]?["text"] != null) { - result += templateBody.render({ - "body": kEncoder.convert(harJson["postData"]["text"]).substring( - 1, kEncoder.convert(harJson["postData"]["text"]).length - 1) - }); - } - } - } - - result = kTemplateStart + result; - result += kStringRequestStart; + var methodTemplate = jj.Template(kTemplateMethod); + result += methodTemplate.render({ + "method": requestModel.method.name, + "hasBody": requestModel.hasBody, + }); var headersList = requestModel.enabledRequestHeaders; - var contentType = requestModel.requestBodyContentType.header; - if (hasBody && - !requestModel.enabledHeadersMap.containsKey('Content-Type')) { - result = - """$result .header("Content-Type", "$contentType")\n"""; - } - if (headersList != null) { + if (headersList != null || requestModel.hasBody) { var headers = requestModel.enabledHeadersMap; + if (requestModel.hasJsonData || requestModel.hasTextData) { + headers.putIfAbsent(kHeaderContentType, + () => requestModel.requestBodyContentType.header); + } + if (requestModel.hasFormData) { + var formDataHeader = jj.Template(kTemplateFormHeaderContentType); + headers.putIfAbsent( + kHeaderContentType, + () => formDataHeader.render({ + "boundary": boundary, + })); + } if (headers.isNotEmpty) { - result += getHeaders(headers, hasJsonBody); + var templateHeader = jj.Template(kTemplateHeader); + result += templateHeader.render({ + "headers": headers, + }); } } - var templateRequestEnd = jj.Template(kTemplateRequestEnd); - - if (kMethodsWithBody.contains(method)) { - result += templateRequestEnd.render({ - "method": method.name.toUpperCase(), - "body": hasBody - ? "BodyPublishers.ofString(body)" - : "BodyPublishers.noBody()" - }); - } else { - result += templateRequestEnd - .render({"method": method.name.toUpperCase(), "body": ""}); - } + var templateEnd = jj.Template(kTemplateEnd); + result += templateEnd.render({ + "hasFormData": requestModel.hasFormData, + "boundary": boundary, + }); } - return result; + + return result.replaceAll(RegExp('\\n\\n+'), '\n\n'); } catch (e) { return null; } } - - String getHeaders(Map headers, hasJsonBody) { - String result = ""; - for (final k in headers.keys) { - if (k.toLowerCase() == 'authorization') { - result = """$result .header("$k", "${headers[k]}")\n"""; - } else { - result = """$result .header("$k", "${headers[k]}")\n"""; - } - } - return result; - } } From d91b5c059bfd8b45d7475629e205c043ef3b63f6 Mon Sep 17 00:00:00 2001 From: Apoorv Dwivedi Date: Sat, 23 Mar 2024 21:33:02 +0530 Subject: [PATCH 049/138] added tests for java http client codegen --- .../codegen/java_httpclient_codegen_test.dart | 1119 +++++++++++++++++ 1 file changed, 1119 insertions(+) create mode 100644 test/codegen/java_httpclient_codegen_test.dart diff --git a/test/codegen/java_httpclient_codegen_test.dart b/test/codegen/java_httpclient_codegen_test.dart new file mode 100644 index 00000000..7ae82b89 --- /dev/null +++ b/test/codegen/java_httpclient_codegen_test.dart @@ -0,0 +1,1119 @@ +import 'package:apidash/codegen/codegen.dart'; +import 'package:apidash/consts.dart'; +import 'package:test/test.dart'; +import '../request_models.dart'; + +void main() { + final codeGen = Codegen(); + + group('GET Request', () { + test('GET1', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet1, "https"), + expectedCode); + }); + test('GET2', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/country/data?code=US"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet2, "https"), + expectedCode); + }); + test('GET3', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/country/data?code=IND"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet3, "https"), + expectedCode); + }); + test('GET4', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/humanize/social?num=8700000&digits=3&system=SS&add_space=true&trailing_zeros=true"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet4, "https"), + expectedCode); + }); + test('GET5', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.github.com/repos/foss42/apidash"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + requestBuilder = requestBuilder.headers( + "User-Agent", "Test Agent" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet5, "https"), + expectedCode); + }); + test('GET6', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.github.com/repos/foss42/apidash?raw=true"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + requestBuilder = requestBuilder.headers( + "User-Agent", "Test Agent" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet6, "https"), + expectedCode); + }); + test('GET7', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet7, "https"), + expectedCode); + }); + test('GET8', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.github.com/repos/foss42/apidash?raw=true"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + requestBuilder = requestBuilder.headers( + "User-Agent", "Test Agent" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet8, "https"), + expectedCode); + }); + test('GET9', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/humanize/social?num=8700000&add_space=true"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet9, "https"), + expectedCode); + }); + test('GET10', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/humanize/social"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + requestBuilder = requestBuilder.headers( + "User-Agent", "Test Agent" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet10, "https"), + expectedCode); + }); + test('GET11', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/humanize/social?num=8700000&digits=3"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + requestBuilder = requestBuilder.headers( + "User-Agent", "Test Agent" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet11, "https"), + expectedCode); + }); + test('GET12', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/humanize/social"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelGet12, "https"), + expectedCode); + }); + }); + + group('HEAD Request', () { + test('HEAD1', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("HEAD", HttpRequest.BodyPublishers.noBody()); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelHead1, "https"), + expectedCode); + }); + test('HEAD2', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("HEAD", HttpRequest.BodyPublishers.noBody()); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelHead2, "https"), + expectedCode); + }); + }); + + group('POST Request', () { + test('POST1', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/case/lower"); + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(""" + { +"text": "I LOVE Flutter" +}"""); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST(bodyPublisher); + requestBuilder = requestBuilder.headers( + "Content-Type", "text/plain" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelPost1, "https"), + expectedCode); + }); + test('POST2', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +import com.google.gson.Gson; +import java.nio.charset.StandardCharsets; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/case/lower"); + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(""" +{ +"text": "I LOVE Flutter", +"flag": null, +"male": true, +"female": false, +"no": 1.2, +"arr": ["null", "true", "false", null] +}"""), StandardCharsets.UTF_8); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST(bodyPublisher); + requestBuilder = requestBuilder.headers( + "Content-Type", "application/json" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelPost2, "https"), + expectedCode); + }); + test('POST3', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +import com.google.gson.Gson; +import java.nio.charset.StandardCharsets; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/case/lower"); + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(""" +{ +"text": "I LOVE Flutter" +}"""), StandardCharsets.UTF_8); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST(bodyPublisher); + requestBuilder = requestBuilder.headers( + "User-Agent", "Test Agent", + "Content-Type", "application/json" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelPost3, "https"), + expectedCode); + }); + test('POST4', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/io/form"); + String boundary = "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"; + Map data = new HashMap<>(); + + data.put("text", "API"); + data.put("sep", "|"); + data.put("times", "3"); + HttpRequest.BodyPublisher bodyPublisher = buildMultipartFormData(data, boundary); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST(bodyPublisher); + requestBuilder = requestBuilder.headers( + "Content-Type", "multipart/form-data; boundary=b9826c20-773c-1f0c-814d-a1b3d90cd6b3" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + + private static HttpRequest.BodyPublisher buildMultipartFormData(Map data, String boundary) throws IOException { + var byteArrays = new ArrayList(); + var CRLF = "\r\n".getBytes(StandardCharsets.UTF_8); + + for (Map.Entry entry : data.entrySet()) { + byteArrays.add(("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8)); + if (entry.getValue() instanceof Path) { + var file = (Path) entry.getValue(); + var fileName = file.getFileName().toString(); + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"; filename=\"" + fileName + "\"\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(("Content-Type: " + Files.probeContentType(file) + "\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(Files.readAllBytes(file)); + byteArrays.add(CRLF); + } else { + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(entry.getValue().toString().getBytes(StandardCharsets.UTF_8)); + byteArrays.add(CRLF); + } + } + byteArrays.add(("--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8)); + + return HttpRequest.BodyPublishers.ofByteArrays(byteArrays); + } +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelPost4, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + expectedCode); + }); + test('POST5', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/io/form"); + String boundary = "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"; + Map data = new HashMap<>(); + + data.put("text", "API"); + data.put("sep", "|"); + data.put("times", "3"); + HttpRequest.BodyPublisher bodyPublisher = buildMultipartFormData(data, boundary); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST(bodyPublisher); + requestBuilder = requestBuilder.headers( + "User-Agent", "Test Agent", + "Content-Type", "multipart/form-data; boundary=b9826c20-773c-1f0c-814d-a1b3d90cd6b3" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + + private static HttpRequest.BodyPublisher buildMultipartFormData(Map data, String boundary) throws IOException { + var byteArrays = new ArrayList(); + var CRLF = "\r\n".getBytes(StandardCharsets.UTF_8); + + for (Map.Entry entry : data.entrySet()) { + byteArrays.add(("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8)); + if (entry.getValue() instanceof Path) { + var file = (Path) entry.getValue(); + var fileName = file.getFileName().toString(); + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"; filename=\"" + fileName + "\"\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(("Content-Type: " + Files.probeContentType(file) + "\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(Files.readAllBytes(file)); + byteArrays.add(CRLF); + } else { + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(entry.getValue().toString().getBytes(StandardCharsets.UTF_8)); + byteArrays.add(CRLF); + } + } + byteArrays.add(("--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8)); + + return HttpRequest.BodyPublishers.ofByteArrays(byteArrays); + } +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelPost5, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + expectedCode); + }); + test('POST6', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/io/img"); + String boundary = "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"; + Map data = new HashMap<>(); + + data.put("token", "xyz"); + data.put("imfile", Paths.get("/Documents/up/1.png")); + HttpRequest.BodyPublisher bodyPublisher = buildMultipartFormData(data, boundary); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST(bodyPublisher); + requestBuilder = requestBuilder.headers( + "Content-Type", "multipart/form-data; boundary=b9826c20-773c-1f0c-814d-a1b3d90cd6b3" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + + private static HttpRequest.BodyPublisher buildMultipartFormData(Map data, String boundary) throws IOException { + var byteArrays = new ArrayList(); + var CRLF = "\r\n".getBytes(StandardCharsets.UTF_8); + + for (Map.Entry entry : data.entrySet()) { + byteArrays.add(("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8)); + if (entry.getValue() instanceof Path) { + var file = (Path) entry.getValue(); + var fileName = file.getFileName().toString(); + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"; filename=\"" + fileName + "\"\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(("Content-Type: " + Files.probeContentType(file) + "\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(Files.readAllBytes(file)); + byteArrays.add(CRLF); + } else { + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(entry.getValue().toString().getBytes(StandardCharsets.UTF_8)); + byteArrays.add(CRLF); + } + } + byteArrays.add(("--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8)); + + return HttpRequest.BodyPublishers.ofByteArrays(byteArrays); + } +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelPost6, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + expectedCode); + }); + test('POST7', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/io/img"); + String boundary = "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"; + Map data = new HashMap<>(); + + data.put("token", "xyz"); + data.put("imfile", Paths.get("/Documents/up/1.png")); + HttpRequest.BodyPublisher bodyPublisher = buildMultipartFormData(data, boundary); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST(bodyPublisher); + requestBuilder = requestBuilder.headers( + "Content-Type", "multipart/form-data; boundary=b9826c20-773c-1f0c-814d-a1b3d90cd6b3" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + + private static HttpRequest.BodyPublisher buildMultipartFormData(Map data, String boundary) throws IOException { + var byteArrays = new ArrayList(); + var CRLF = "\r\n".getBytes(StandardCharsets.UTF_8); + + for (Map.Entry entry : data.entrySet()) { + byteArrays.add(("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8)); + if (entry.getValue() instanceof Path) { + var file = (Path) entry.getValue(); + var fileName = file.getFileName().toString(); + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"; filename=\"" + fileName + "\"\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(("Content-Type: " + Files.probeContentType(file) + "\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(Files.readAllBytes(file)); + byteArrays.add(CRLF); + } else { + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(entry.getValue().toString().getBytes(StandardCharsets.UTF_8)); + byteArrays.add(CRLF); + } + } + byteArrays.add(("--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8)); + + return HttpRequest.BodyPublishers.ofByteArrays(byteArrays); + } +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelPost7, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + expectedCode); + }); + test('POST8', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/io/form?size=2&len=3"); + String boundary = "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"; + Map data = new HashMap<>(); + + data.put("text", "API"); + data.put("sep", "|"); + data.put("times", "3"); + HttpRequest.BodyPublisher bodyPublisher = buildMultipartFormData(data, boundary); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST(bodyPublisher); + requestBuilder = requestBuilder.headers( + "Content-Type", "multipart/form-data; boundary=b9826c20-773c-1f0c-814d-a1b3d90cd6b3" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + + private static HttpRequest.BodyPublisher buildMultipartFormData(Map data, String boundary) throws IOException { + var byteArrays = new ArrayList(); + var CRLF = "\r\n".getBytes(StandardCharsets.UTF_8); + + for (Map.Entry entry : data.entrySet()) { + byteArrays.add(("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8)); + if (entry.getValue() instanceof Path) { + var file = (Path) entry.getValue(); + var fileName = file.getFileName().toString(); + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"; filename=\"" + fileName + "\"\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(("Content-Type: " + Files.probeContentType(file) + "\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(Files.readAllBytes(file)); + byteArrays.add(CRLF); + } else { + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(entry.getValue().toString().getBytes(StandardCharsets.UTF_8)); + byteArrays.add(CRLF); + } + } + byteArrays.add(("--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8)); + + return HttpRequest.BodyPublishers.ofByteArrays(byteArrays); + } +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelPost8, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + expectedCode); + }); + test('POST9', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://api.apidash.dev/io/img?size=2&len=3"); + String boundary = "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"; + Map data = new HashMap<>(); + + data.put("token", "xyz"); + data.put("imfile", Paths.get("/Documents/up/1.png")); + HttpRequest.BodyPublisher bodyPublisher = buildMultipartFormData(data, boundary); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST(bodyPublisher); + requestBuilder = requestBuilder.headers( + "User-Agent", "Test Agent", + "Keep-Alive", "true", + "Content-Type", "multipart/form-data; boundary=b9826c20-773c-1f0c-814d-a1b3d90cd6b3" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + + private static HttpRequest.BodyPublisher buildMultipartFormData(Map data, String boundary) throws IOException { + var byteArrays = new ArrayList(); + var CRLF = "\r\n".getBytes(StandardCharsets.UTF_8); + + for (Map.Entry entry : data.entrySet()) { + byteArrays.add(("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8)); + if (entry.getValue() instanceof Path) { + var file = (Path) entry.getValue(); + var fileName = file.getFileName().toString(); + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"; filename=\"" + fileName + "\"\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(("Content-Type: " + Files.probeContentType(file) + "\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(Files.readAllBytes(file)); + byteArrays.add(CRLF); + } else { + byteArrays.add(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n").getBytes(StandardCharsets.UTF_8)); + byteArrays.add(entry.getValue().toString().getBytes(StandardCharsets.UTF_8)); + byteArrays.add(CRLF); + } + } + byteArrays.add(("--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8)); + + return HttpRequest.BodyPublishers.ofByteArrays(byteArrays); + } +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelPost9, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + expectedCode); + }); + }); + + group('PUT Request', () { + test('PUT1', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +import com.google.gson.Gson; +import java.nio.charset.StandardCharsets; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://reqres.in/api/users/2"); + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(""" +{ +"name": "morpheus", +"job": "zion resident" +}"""), StandardCharsets.UTF_8); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).PUT(bodyPublisher); + requestBuilder = requestBuilder.headers( + "Content-Type", "application/json" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelPut1, "https"), + expectedCode); + }); + }); + + group('PATCH Request', () { + test('PATCH1', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +import com.google.gson.Gson; +import java.nio.charset.StandardCharsets; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://reqres.in/api/users/2"); + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(""" +{ +"name": "marfeus", +"job": "accountant" +}"""), StandardCharsets.UTF_8); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("PATCH", bodyPublisher); + requestBuilder = requestBuilder.headers( + "Content-Type", "application/json" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelPatch1, "https"), + expectedCode); + }); + }); + + group('DELETE Request', () { + test('DELETE1', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://reqres.in/api/users/2"); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("DELETE", HttpRequest.BodyPublishers.noBody()); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelDelete1, "https"), + expectedCode); + }); + test('DELETE2', () { + const expectedCode = r''' +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.io.IOException; + +import com.google.gson.Gson; +import java.nio.charset.StandardCharsets; + +public class Main { + public static void main(String[] args) { + try { + HttpClient client = HttpClient.newHttpClient(); + URI uri = URI.create("https://reqres.in/api/users/2"); + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(""" +{ +"name": "marfeus", +"job": "accountant" +}"""), StandardCharsets.UTF_8); + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("DELETE", bodyPublisher); + requestBuilder = requestBuilder.headers( + "Content-Type", "application/json" + ); + HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + System.out.println("Response body: " + response.body()); + System.out.println("Response code: " + response.statusCode()); + } catch (IOException | InterruptedException e) { + System.out.println("An error occurred: " + e.getMessage()); + } + } + +}'''; + expect( + codeGen.getCode( + CodegenLanguage.javaHttpClient, requestModelDelete2, "https"), + expectedCode); + }); + }); + +} From dbc4aec6fd62826a0733e55025c6450cb89ad69c Mon Sep 17 00:00:00 2001 From: DenserMeerkat Date: Sat, 23 Mar 2024 21:52:06 +0530 Subject: [PATCH 050/138] fix: added missing setState --- .../editor_pane/details_card/request_pane/request_form_data.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart index 3f8d52d5..554f582a 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart @@ -114,6 +114,7 @@ class _FormDataBodyState extends ConsumerState { if (isLast && hasChanged) { formRows.add(kFormDataEmptyModel); } + setState(() {}); _onFieldChange(selectedId!); }, ), From 2ef3a82cc99a73d1169ebc5ddf29f947f842b442 Mon Sep 17 00:00:00 2001 From: DenserMeerkat Date: Sat, 23 Mar 2024 23:39:57 +0530 Subject: [PATCH 051/138] fix: resolve conflict errors --- lib/consts.dart | 2 +- .../request_pane/request_form_data.dart | 27 ++++++++++--------- .../request_pane/request_headers.dart | 27 ++++++++++--------- .../request_pane/request_params.dart | 27 ++++++++++--------- 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index 8947da81..58a1b757 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -132,7 +132,7 @@ const kRandMax = 100000; const kDataTableScrollbarTheme = ScrollbarThemeData( crossAxisMargin: -4, ); -const kDataTableBottomPadding = 80.0; +const kDataTableBottomPadding = 12.0; const kDataTableRowHeight = 36.0; const kIconRemoveDark = Icon( diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart index 554f582a..fb9c40dd 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart @@ -52,7 +52,7 @@ class _FormDataBodyState extends ConsumerState { List columns = const [ DataColumn2( - label: Text('Key'), + label: Text(kNameField), size: ColumnSize.M, ), DataColumn2( @@ -60,15 +60,15 @@ class _FormDataBodyState extends ConsumerState { fixedWidth: 20, ), DataColumn2( - label: Text('Type'), + label: Text(''), fixedWidth: 70, ), DataColumn2( - label: Text('Value'), + label: Text(kNameValue), size: ColumnSize.L, ), DataColumn2( - label: Text('Remove'), + label: Text(''), fixedWidth: 32, ), ]; @@ -84,7 +84,7 @@ class _FormDataBodyState extends ConsumerState { CellField( keyId: "$selectedId-$index-form-k-$seed", initialValue: formRows[index].name, - hintText: " Add Key", + hintText: kHintAddFieldName, onChanged: (value) { formRows[index] = formRows[index].copyWith(name: value); if (isLast && !isAddingRow) { @@ -97,9 +97,11 @@ class _FormDataBodyState extends ConsumerState { ), ), DataCell( - Text( - "=", - style: kCodeStyle, + Center( + child: Text( + "=", + style: kCodeStyle, + ), ), ), DataCell( @@ -148,7 +150,7 @@ class _FormDataBodyState extends ConsumerState { (formRows[index].type == FormDataType.file && formRows[index].value.isNotEmpty) ? formRows[index].value.toString() - : "Select File", + : kLabelSelectFile, overflow: TextOverflow.ellipsis, style: kFormDataButtonLabelTextStyle, ), @@ -156,7 +158,7 @@ class _FormDataBodyState extends ConsumerState { : CellField( keyId: "$selectedId-$index-form-v-$seed", initialValue: formRows[index].value, - hintText: " Add Value", + hintText: kHintAddValue, onChanged: (value) { formRows[index] = formRows[index].copyWith(value: value); @@ -223,13 +225,14 @@ class _FormDataBodyState extends ConsumerState { ), ), ), + kVSpacer20, ], ), ), Align( alignment: Alignment.bottomCenter, child: Padding( - padding: const EdgeInsets.only(bottom: 30), + padding: const EdgeInsets.only(bottom: 5), child: ElevatedButton.icon( onPressed: () { formRows.add(kFormDataEmptyModel); @@ -237,7 +240,7 @@ class _FormDataBodyState extends ConsumerState { }, icon: const Icon(Icons.add), label: const Text( - "Add Form Data", + kLabelAddFormField, style: kTextStyleButton, ), ), diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart index 686e9535..ab8efec3 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart @@ -56,21 +56,21 @@ class EditRequestHeadersState extends ConsumerState { List columns = const [ DataColumn2( - label: Text('Checkbox'), + label: Text(kNameCheckbox), fixedWidth: 30, ), DataColumn2( - label: Text('Header Name'), + label: Text(kNameHeader), ), DataColumn2( label: Text('='), - fixedWidth: 22, + fixedWidth: 30, ), DataColumn2( - label: Text('Header Value'), + label: Text(kNameValue), ), DataColumn2( - label: Text('Remove'), + label: Text(''), fixedWidth: 32, ), ]; @@ -101,7 +101,7 @@ class EditRequestHeadersState extends ConsumerState { HeaderField( keyId: "$selectedId-$index-headers-k-$seed", initialValue: headerRows[index].name, - hintText: "Add Header Name", + hintText: kHintAddName, onChanged: (value) { headerRows[index] = headerRows[index].copyWith(name: value); if (isLast && !isAddingRow) { @@ -116,16 +116,18 @@ class EditRequestHeadersState extends ConsumerState { ), ), DataCell( - Text( - "=", - style: kCodeStyle, + Center( + child: Text( + "=", + style: kCodeStyle, + ), ), ), DataCell( CellField( keyId: "$selectedId-$index-headers-v-$seed", initialValue: headerRows[index].value, - hintText: " Add Header Value", + hintText: kHintAddValue, onChanged: (value) { headerRows[index] = headerRows[index].copyWith(value: value); if (isLast && !isAddingRow) { @@ -195,13 +197,14 @@ class EditRequestHeadersState extends ConsumerState { ), ), ), + kVSpacer40, ], ), ), Align( alignment: Alignment.bottomCenter, child: Padding( - padding: const EdgeInsets.only(bottom: 30), + padding: kPb15, child: ElevatedButton.icon( onPressed: () { headerRows.add(kNameValueEmptyModel); @@ -210,7 +213,7 @@ class EditRequestHeadersState extends ConsumerState { }, icon: const Icon(Icons.add), label: const Text( - "Add Header", + kLabelAddHeader, style: kTextStyleButton, ), ), diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart index 4836937d..4b048c0a 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_params.dart @@ -56,21 +56,21 @@ class EditRequestURLParamsState extends ConsumerState { List columns = const [ DataColumn2( - label: Text('Checkbox'), + label: Text(kNameCheckbox), fixedWidth: 30, ), DataColumn2( - label: Text('URL Parameter'), + label: Text(kNameURLParam), ), DataColumn2( label: Text('='), - fixedWidth: 22, + fixedWidth: 30, ), DataColumn2( - label: Text('Parameter Value'), + label: Text(kNameValue), ), DataColumn2( - label: Text('Remove'), + label: Text(''), fixedWidth: 32, ), ]; @@ -101,7 +101,7 @@ class EditRequestURLParamsState extends ConsumerState { CellField( keyId: "$selectedId-$index-params-k-$seed", initialValue: paramRows[index].name, - hintText: "Add URL Parameter", + hintText: kHintAddURLParam, onChanged: (value) { paramRows[index] = paramRows[index].copyWith(name: value); if (isLast && !isAddingRow) { @@ -116,16 +116,18 @@ class EditRequestURLParamsState extends ConsumerState { ), ), DataCell( - Text( - "=", - style: kCodeStyle, + Center( + child: Text( + "=", + style: kCodeStyle, + ), ), ), DataCell( CellField( keyId: "$selectedId-$index-params-v-$seed", initialValue: paramRows[index].value, - hintText: "Add Value", + hintText: kHintAddValue, onChanged: (value) { paramRows[index] = paramRows[index].copyWith(value: value); if (isLast && !isAddingRow) { @@ -196,13 +198,14 @@ class EditRequestURLParamsState extends ConsumerState { ), ), ), + kVSpacer40, ], ), ), Align( alignment: Alignment.bottomCenter, child: Padding( - padding: const EdgeInsets.only(bottom: 30), + padding: kPb15, child: ElevatedButton.icon( onPressed: () { paramRows.add(kNameValueEmptyModel); @@ -211,7 +214,7 @@ class EditRequestURLParamsState extends ConsumerState { }, icon: const Icon(Icons.add), label: const Text( - "Add Param", + kLabelAddParam, style: kTextStyleButton, ), ), From fa0b02d67195bf818391972330a4490cc8317f0f Mon Sep 17 00:00:00 2001 From: DenserMeerkat Date: Sun, 24 Mar 2024 00:02:29 +0530 Subject: [PATCH 052/138] fix: request form data padding --- .../details_card/request_pane/request_form_data.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart index fb9c40dd..a0388612 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart @@ -225,14 +225,14 @@ class _FormDataBodyState extends ConsumerState { ), ), ), - kVSpacer20, + kVSpacer40, ], ), ), Align( alignment: Alignment.bottomCenter, child: Padding( - padding: const EdgeInsets.only(bottom: 5), + padding: kPb15, child: ElevatedButton.icon( onPressed: () { formRows.add(kFormDataEmptyModel); From 5a9dd7c07e98304fc4b6594d6376aa61fdf232d1 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 24 Mar 2024 01:18:28 +0530 Subject: [PATCH 053/138] Refactor --- lib/providers/collection_providers.dart | 35 +------------ lib/providers/ui_providers.dart | 2 + lib/screens/home_page/collection_pane.dart | 61 +++++++++++++--------- lib/widgets/textfields.dart | 31 +++++++++-- 4 files changed, 66 insertions(+), 63 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 30801ecb..db6b7cf3 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -1,4 +1,3 @@ -import 'package:collection/collection.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'settings_providers.dart'; import 'ui_providers.dart'; @@ -9,7 +8,6 @@ import '../consts.dart'; import 'package:http/http.dart' as http; final selectedIdStateProvider = StateProvider((ref) => null); -final searchQueryProvider = StateProvider((ref) => ''); final selectedRequestModelProvider = StateProvider((ref) { final selectedId = ref.watch(selectedIdStateProvider); @@ -33,7 +31,7 @@ final StateNotifierProvider?> class CollectionStateNotifier extends StateNotifier?> { CollectionStateNotifier(this.ref, this.hiveHandler) : super(null) { - var status = filterRequests(ref.read(searchQueryProvider.notifier).state); + var status = loadData(); Future.microtask(() { if (status) { ref.read(requestSequenceProvider.notifier).state = [ @@ -250,37 +248,6 @@ class CollectionStateNotifier } } - bool filterRequests(String query) { - if (query.isEmpty) { - - loadData(); - return true; - } else { - // Filter requests based on the query - final filteredRequests = state?.values.where((request) => - request.name.toLowerCase().contains(query.toLowerCase())).toList(); - - - if (filteredRequests != null && filteredRequests.isNotEmpty) { - - Map requestMap = {}; - - for (var request in filteredRequests) { - requestMap[request.id] = request; - } - - state = requestMap; - - } else { - print("No matching requests found"); - } - - - - return false; - } - } - Future saveData() async { ref.read(saveDataStateProvider.notifier).state = true; final saveResponse = ref.read(settingsProvider).saveResponses; diff --git a/lib/providers/ui_providers.dart b/lib/providers/ui_providers.dart index 2fddb2ad..62f83f70 100644 --- a/lib/providers/ui_providers.dart +++ b/lib/providers/ui_providers.dart @@ -23,3 +23,5 @@ final nameTextFieldFocusNodeProvider = }); return focusNode; }); + +final searchQueryProvider = StateProvider((ref) => ''); diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index c44ed56e..abfc1f28 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; @@ -67,33 +66,44 @@ class CollectionPane extends ConsumerWidget { style: kTextStyleButton, ), ), - ], ), ), kVSpacer10, - SizedBox( - height:30, - child:SearchBar( - - onChanged: (value){ - if(value.isNotEmpty){ - ref.read(searchQueryProvider.notifier).state = value; - ref.read(collectionStateNotifierProvider.notifier) - .filterRequests(value); - } - else{ - - } - - }, - hintText: "search", - leading: Icon(Icons.search), - textStyle: MaterialStateTextStyle.resolveWith((states) => TextStyle(fontSize: 15.0)), - elevation: MaterialStateProperty.all(2.0), - )), + Container( + height: 30, + margin: const EdgeInsets.only(right: 8), + decoration: BoxDecoration( + borderRadius: kBorderRadius8, + border: Border.all( + color: Theme.of(context).colorScheme.surfaceVariant, + ), + ), + child: Row( + children: [ + kHSpacer5, + Icon( + Icons.filter_alt, + size: 18, + color: Theme.of(context).colorScheme.secondary, + ), + kHSpacer5, + Expanded( + child: RawTextField( + style: Theme.of(context).textTheme.bodyMedium, + hintText: "Filter by name or URL", + onChanged: (value) { + if (value.trim().isNotEmpty) { + ref.read(searchQueryProvider.notifier).state = value; + print(value); + } + }, + ), + ), + ], + ), + ), kVSpacer10, - const Expanded( child: RequestList(), ), @@ -134,7 +144,7 @@ class _RequestListState extends ConsumerState { final alwaysShowCollectionPaneScrollbar = ref.watch(settingsProvider .select((value) => value.alwaysShowCollectionPaneScrollbar)); - return requestItems.isNotEmpty?Scrollbar( + return Scrollbar( controller: controller, thumbVisibility: alwaysShowCollectionPaneScrollbar ? true : null, radius: const Radius.circular(12), @@ -155,7 +165,6 @@ class _RequestListState extends ConsumerState { }, itemBuilder: (context, index) { var id = requestSequence[index]; - print(requestItems[id]!); return ReorderableDragStartListener( key: ValueKey(id), @@ -170,7 +179,7 @@ class _RequestListState extends ConsumerState { ); }, ), - ):Text("data"); + ); } } diff --git a/lib/widgets/textfields.dart b/lib/widgets/textfields.dart index da68f9e2..35d3437f 100644 --- a/lib/widgets/textfields.dart +++ b/lib/widgets/textfields.dart @@ -94,14 +94,39 @@ class JsonSearchField extends StatelessWidget { @override Widget build(BuildContext context) { - return TextField( + return RawTextField( controller: controller, onChanged: onChanged, style: kCodeStyle, - decoration: const InputDecoration( + hintText: 'Search..', + ); + } +} + +class RawTextField extends StatelessWidget { + const RawTextField({ + super.key, + this.onChanged, + this.controller, + this.hintText, + this.style, + }); + + final void Function(String)? onChanged; + final TextEditingController? controller; + final String? hintText; + final TextStyle? style; + + @override + Widget build(BuildContext context) { + return TextField( + controller: controller, + onChanged: onChanged, + style: style, + decoration: InputDecoration( isDense: true, border: InputBorder.none, - hintText: 'Search..', + hintText: hintText, ), ); } From 77cb9db9a35566a7c0b543026a3c092ca2a0be55 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 24 Mar 2024 01:20:38 +0530 Subject: [PATCH 054/138] Update collection_pane.dart --- lib/screens/home_page/collection_pane.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index abfc1f28..1ba202eb 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -165,7 +165,6 @@ class _RequestListState extends ConsumerState { }, itemBuilder: (context, index) { var id = requestSequence[index]; - return ReorderableDragStartListener( key: ValueKey(id), index: index, From 3886755ae92489b710520799a4c456406e48e442 Mon Sep 17 00:00:00 2001 From: Apoorv Dwivedi Date: Sun, 24 Mar 2024 01:54:33 +0530 Subject: [PATCH 055/138] fixed json body and head2 --- lib/codegen/java/httpclient.dart | 7 +--- .../codegen/java_httpclient_codegen_test.dart | 37 ++++++------------- 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/lib/codegen/java/httpclient.dart b/lib/codegen/java/httpclient.dart index e113fa10..01d45b05 100644 --- a/lib/codegen/java/httpclient.dart +++ b/lib/codegen/java/httpclient.dart @@ -17,8 +17,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.charset.StandardCharsets; import java.util.ArrayList;{% endif %} -{% if hasJsonBody %}import com.google.gson.Gson; -import java.nio.charset.StandardCharsets;{% endif %} public class Main { public static void main(String[] args) { @@ -57,8 +55,8 @@ multipart/form-data; boundary={{boundary}}'''; """; String kTemplateJsonBody = """ - HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(\"\"\" -{{body}}\"\"\"), StandardCharsets.UTF_8); + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(\"\"\" +{{body}}\"\"\"); """; String kTemplateFormData = """ @@ -121,7 +119,6 @@ multipart/form-data; boundary={{boundary}}'''; String url = requestModel.url; result += jj.Template(kTemplateStart).render({ - "hasJsonBody": requestModel.hasJsonData, "hasFormData": requestModel.hasFormData, }); diff --git a/test/codegen/java_httpclient_codegen_test.dart b/test/codegen/java_httpclient_codegen_test.dart index 7ae82b89..0fc25e2a 100644 --- a/test/codegen/java_httpclient_codegen_test.dart +++ b/test/codegen/java_httpclient_codegen_test.dart @@ -428,7 +428,7 @@ public class Main { }'''; expect( codeGen.getCode( - CodegenLanguage.javaHttpClient, requestModelHead2, "https"), + CodegenLanguage.javaHttpClient, requestModelHead2, "http"), expectedCode); }); }); @@ -477,15 +477,12 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.io.IOException; -import com.google.gson.Gson; -import java.nio.charset.StandardCharsets; - public class Main { public static void main(String[] args) { try { HttpClient client = HttpClient.newHttpClient(); URI uri = URI.create("https://api.apidash.dev/case/lower"); - HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(""" + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(""" { "text": "I LOVE Flutter", "flag": null, @@ -493,7 +490,7 @@ public class Main { "female": false, "no": 1.2, "arr": ["null", "true", "false", null] -}"""), StandardCharsets.UTF_8); +}"""); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST(bodyPublisher); requestBuilder = requestBuilder.headers( "Content-Type", "application/json" @@ -520,18 +517,15 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.io.IOException; -import com.google.gson.Gson; -import java.nio.charset.StandardCharsets; - public class Main { public static void main(String[] args) { try { HttpClient client = HttpClient.newHttpClient(); URI uri = URI.create("https://api.apidash.dev/case/lower"); - HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(""" + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(""" { "text": "I LOVE Flutter" -}"""), StandardCharsets.UTF_8); +}"""); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST(bodyPublisher); requestBuilder = requestBuilder.headers( "User-Agent", "Test Agent", @@ -970,19 +964,16 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.io.IOException; -import com.google.gson.Gson; -import java.nio.charset.StandardCharsets; - public class Main { public static void main(String[] args) { try { HttpClient client = HttpClient.newHttpClient(); URI uri = URI.create("https://reqres.in/api/users/2"); - HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(""" + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(""" { "name": "morpheus", "job": "zion resident" -}"""), StandardCharsets.UTF_8); +}"""); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).PUT(bodyPublisher); requestBuilder = requestBuilder.headers( "Content-Type", "application/json" @@ -1012,19 +1003,16 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.io.IOException; -import com.google.gson.Gson; -import java.nio.charset.StandardCharsets; - public class Main { public static void main(String[] args) { try { HttpClient client = HttpClient.newHttpClient(); URI uri = URI.create("https://reqres.in/api/users/2"); - HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(""" + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(""" { "name": "marfeus", "job": "accountant" -}"""), StandardCharsets.UTF_8); +}"""); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("PATCH", bodyPublisher); requestBuilder = requestBuilder.headers( "Content-Type", "application/json" @@ -1083,19 +1071,16 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.io.IOException; -import com.google.gson.Gson; -import java.nio.charset.StandardCharsets; - public class Main { public static void main(String[] args) { try { HttpClient client = HttpClient.newHttpClient(); URI uri = URI.create("https://reqres.in/api/users/2"); - HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(new Gson().toJson(""" + HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(""" { "name": "marfeus", "job": "accountant" -}"""), StandardCharsets.UTF_8); +}"""); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("DELETE", bodyPublisher); requestBuilder = requestBuilder.headers( "Content-Type", "application/json" From 1451ea756702f58e4dc7b9aac2d1ca542dcc37c0 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 24 Mar 2024 02:37:47 +0530 Subject: [PATCH 056/138] Update collection_pane.dart --- lib/screens/home_page/collection_pane.dart | 68 +++++++++++----------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index 1ba202eb..7d89a375 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -93,10 +93,7 @@ class CollectionPane extends ConsumerWidget { style: Theme.of(context).textTheme.bodyMedium, hintText: "Filter by name or URL", onChanged: (value) { - if (value.trim().isNotEmpty) { - ref.read(searchQueryProvider.notifier).state = value; - print(value); - } + ref.read(searchQueryProvider.notifier).state = value; }, ), ), @@ -143,41 +140,44 @@ class _RequestListState extends ConsumerState { final requestItems = ref.watch(collectionStateNotifierProvider)!; final alwaysShowCollectionPaneScrollbar = ref.watch(settingsProvider .select((value) => value.alwaysShowCollectionPaneScrollbar)); + final filterQuery = ref.watch(searchQueryProvider).trim(); return Scrollbar( controller: controller, thumbVisibility: alwaysShowCollectionPaneScrollbar ? true : null, radius: const Radius.circular(12), - child: ReorderableListView.builder( - padding: kPr8CollectionPane, - scrollController: controller, - buildDefaultDragHandles: false, - itemCount: requestItems.length, - onReorder: (int oldIndex, int newIndex) { - if (oldIndex < newIndex) { - newIndex -= 1; - } - if (oldIndex != newIndex) { - ref - .read(collectionStateNotifierProvider.notifier) - .reorder(oldIndex, newIndex); - } - }, - itemBuilder: (context, index) { - var id = requestSequence[index]; - return ReorderableDragStartListener( - key: ValueKey(id), - index: index, - child: Padding( - padding: kP1, - child: RequestItem( - id: id, - requestModel: requestItems[id]!, - ), - ), - ); - }, - ), + child: filterQuery.isEmpty + ? ReorderableListView.builder( + padding: kPr8CollectionPane, + scrollController: controller, + buildDefaultDragHandles: false, + itemCount: requestItems.length, + onReorder: (int oldIndex, int newIndex) { + if (oldIndex < newIndex) { + newIndex -= 1; + } + if (oldIndex != newIndex) { + ref + .read(collectionStateNotifierProvider.notifier) + .reorder(oldIndex, newIndex); + } + }, + itemBuilder: (context, index) { + var id = requestSequence[index]; + return ReorderableDragStartListener( + key: ValueKey(id), + index: index, + child: Padding( + padding: kP1, + child: RequestItem( + id: id, + requestModel: requestItems[id]!, + ), + ), + ); + }, + ) + : SizedBox(), ); } } From 4243904aa97d9fbb3d5a4d701312eb343bea9d66 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 24 Mar 2024 02:56:28 +0530 Subject: [PATCH 057/138] Filtered list --- lib/screens/home_page/collection_pane.dart | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index d377e786..0ede2021 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -93,7 +93,8 @@ class CollectionPane extends ConsumerWidget { style: Theme.of(context).textTheme.bodyMedium, hintText: "Filter by name or URL", onChanged: (value) { - ref.read(searchQueryProvider.notifier).state = value; + ref.read(searchQueryProvider.notifier).state = + value.toLowerCase(); }, ), ), @@ -177,7 +178,24 @@ class _RequestListState extends ConsumerState { ); }, ) - : SizedBox(), + : ListView( + padding: kPe8, + controller: controller, + children: requestSequence.map((id) { + var item = requestItems[id]!; + if (item.url.toLowerCase().contains(filterQuery) || + item.name.toLowerCase().contains(filterQuery)) { + return Padding( + padding: kP1, + child: RequestItem( + id: id, + requestModel: item, + ), + ); + } + return const SizedBox(); + }).toList(), + ), ); } } From 8a8ded7d203fd00bb78374cfef6bea020278e113 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 24 Mar 2024 03:18:04 +0530 Subject: [PATCH 058/138] Update tests --- test/providers/ui_providers_test.dart | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index dde4983f..9d34619d 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -214,13 +214,13 @@ void main() { }); group("Testing selectedIdEditStateProvider", () { - testWidgets( - 'selectedIdEditStateProvider should have an initial value of null', - (tester) async { + testWidgets('It should have an initial value of null', (tester) async { await tester.pumpWidget( const ProviderScope( child: MaterialApp( - home: CollectionPane(), + home: Scaffold( + body: CollectionPane(), + ), ), ), ); @@ -237,7 +237,9 @@ void main() { await tester.pumpWidget( const ProviderScope( child: MaterialApp( - home: CollectionPane(), + home: Scaffold( + body: CollectionPane(), + ), ), ), ); @@ -267,7 +269,9 @@ void main() { await tester.pumpWidget( const ProviderScope( child: MaterialApp( - home: CollectionPane(), + home: Scaffold( + body: CollectionPane(), + ), ), ), ); @@ -303,7 +307,9 @@ void main() { await tester.pumpWidget( const ProviderScope( child: MaterialApp( - home: CollectionPane(), + home: Scaffold( + body: CollectionPane(), + ), ), ), ); From ef48f2947fddd06a029c34f8107344271d84b8ca Mon Sep 17 00:00:00 2001 From: Yousef Rabia Date: Sun, 24 Mar 2024 03:49:21 +0200 Subject: [PATCH 059/138] Replace SingleChildScrollView and Column with Stack --- lib/widgets/response_widgets.dart | 56 ++++++++++++++++--------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index a2f2183a..8228f781 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:http_parser/http_parser.dart'; @@ -74,36 +75,37 @@ class _SendingWidgetState extends State { @override Widget build(BuildContext context) { - return Center( - child: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Visibility( - visible: _millisecondsElapsed >= 0, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.alarm), - const SizedBox( - width: 10, - ), - Text( - 'Time elapsed: ${humanizeDuration(Duration(milliseconds: _millisecondsElapsed))}', - textAlign: TextAlign.center, - overflow: TextOverflow.fade, - softWrap: false, - style: kTextStyleButton, - ), - ], - ), - ), - Lottie.asset(kAssetSendingLottie), - ], + return Stack( + children: [ + Center( + child: Lottie.asset(kAssetSendingLottie), ), - ), + Padding( + padding: kPh20t40, + child: Visibility( + visible: _millisecondsElapsed >= 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.alarm), + const SizedBox( + width: 10, + ), + Text( + 'Time elapsed: ${humanizeDuration(Duration(milliseconds: _millisecondsElapsed))}', + textAlign: TextAlign.center, + overflow: TextOverflow.fade, + softWrap: false, + style: kTextStyleButton, + ), + ], + ), + ), + ), + ], ); } + } class ResponsePaneHeader extends StatelessWidget { From f9f185ece97ca3e43d6ff2c2e7f513c7b84c5e50 Mon Sep 17 00:00:00 2001 From: Tanish2002 Date: Sun, 24 Mar 2024 20:11:44 +0530 Subject: [PATCH 060/138] fix: file picker on linux --- .../request_pane/request_form_data.dart | 5 +- lib/utils/file_utils.dart | 6 +- pubspec.lock | 80 ++++++++++++++++--- pubspec.yaml | 2 +- 4 files changed, 74 insertions(+), 19 deletions(-) diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart index a6bafd6e..582b19ed 100644 --- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart +++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart @@ -132,10 +132,9 @@ class _FormDataBodyState extends ConsumerState { onPressed: () async { var pickedResult = await pickFile(); if (pickedResult != null && - pickedResult.files.isNotEmpty && - pickedResult.files.first.path != null) { + pickedResult.path.isNotEmpty) { formRows[idx] = formRows[idx].copyWith( - value: pickedResult.files.first.path!, + value: pickedResult.path, ); setState(() {}); _onFieldChange(selectedId!); diff --git a/lib/utils/file_utils.dart b/lib/utils/file_utils.dart index 58d69513..8f7c6a72 100644 --- a/lib/utils/file_utils.dart +++ b/lib/utils/file_utils.dart @@ -1,10 +1,10 @@ import 'dart:io'; import 'dart:typed_data'; +import 'package:file_selector/file_selector.dart'; import 'package:path/path.dart' as p; import 'package:mime_dart/mime_dart.dart'; import 'package:uuid/uuid.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:file_picker/file_picker.dart'; const uuid = Uuid(); @@ -57,7 +57,7 @@ String getTempFileName() { return getNewUuid(); } -Future pickFile() async { - FilePickerResult? pickedResult = await FilePicker.platform.pickFiles(); +Future pickFile() async { + XFile? pickedResult = await openFile(); return pickedResult; } diff --git a/pubspec.lock b/pubspec.lock index a4e54dfb..3d7a7189 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -209,6 +209,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.7.2" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" + url: "https://pub.dev" + source: hosted + version: "0.3.4+1" crypto: dependency: transitive description: @@ -289,14 +297,70 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" - file_picker: + file_selector: dependency: "direct main" description: - name: file_picker - sha256: caa6bc229eab3e32eb2f37b53a5f9d22a6981474afd210c512a7546c1e1a04f6 + name: file_selector + sha256: "5019692b593455127794d5718304ff1ae15447dea286cdda9f0db2a796a1b828" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "1.0.3" + file_selector_android: + dependency: transitive + description: + name: file_selector_android + sha256: "1cd66575f063b689e041aec836905ba7be18d76c9f0634d0d75daec825f67095" + url: "https://pub.dev" + source: hosted + version: "0.5.0+7" + file_selector_ios: + dependency: transitive + description: + name: file_selector_ios + sha256: b015154e6d9fddbc4d08916794df170b44531798c8dd709a026df162d07ad81d + url: "https://pub.dev" + source: hosted + version: "0.5.1+8" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: b15c3da8bd4908b9918111fa486903f5808e388b8d1c559949f584725a6594d6 + url: "https://pub.dev" + source: hosted + version: "0.9.3+3" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_web: + dependency: transitive + description: + name: file_selector_web + sha256: "619e431b224711a3869e30dbd7d516f5f5a4f04b265013a50912f39e1abc88c8" + url: "https://pub.dev" + source: hosted + version: "0.9.4+1" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" fixnum: dependency: transitive description: @@ -382,14 +446,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.21" - flutter_plugin_android_lifecycle: - dependency: transitive - description: - name: flutter_plugin_android_lifecycle - sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da - url: "https://pub.dev" - source: hosted - version: "2.0.17" flutter_riverpod: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index b7c79bde..cfa20cb3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -49,13 +49,13 @@ dependencies: url: https://github.com/foss42/json_data_explorer.git ref: b7dde2f85dff4f482eed7eda4ef2a71344ef8b3a scrollable_positioned_list: ^0.3.8 - file_picker: ^6.2.0 flutter_svg: ^2.0.10+1 vector_graphics_compiler: ^1.1.9+1 code_builder: ^4.10.0 dart_style: ^2.3.6 json_text_field: ^1.1.0 csv: ^6.0.0 + file_selector: ^1.0.3 dependency_overrides: web: ^0.5.0 From 19b2a1e2bc61fd6212a39e5407bd3f8a1098738b Mon Sep 17 00:00:00 2001 From: Tilakraj-B Date: Mon, 25 Mar 2024 21:15:17 +0530 Subject: [PATCH 061/138] removed redundant functions --- lib/codegen/csharp/rest_sharp.dart | 10 +++++++--- lib/utils/http_utils.dart | 10 ---------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/lib/codegen/csharp/rest_sharp.dart b/lib/codegen/csharp/rest_sharp.dart index c31a13a0..18a7219b 100644 --- a/lib/codegen/csharp/rest_sharp.dart +++ b/lib/codegen/csharp/rest_sharp.dart @@ -79,15 +79,19 @@ class Program result += kStringInit; + Uri uri = + getValidRequestUri(requestModel.url, requestModel.requestParams).$1!; + var baseUrl = + "${uri.scheme}://${uri.host}${uri.hasPort ? ":${uri.port}" : ""}${uri.hasFragment ? "#${uri.fragment}" : ""}"; + jj.Template templateInitClient = jj.Template(kInitClientTemplate); - String initClient = - templateInitClient.render({"baseUrl": getBaseUrl(requestModel.url)}); + String initClient = templateInitClient.render({"baseUrl": baseUrl}); result += initClient; result += kStringLineBreak; jj.Template templateMethodType = jj.Template(kMethodTypeTemplate); String methodType = templateMethodType.render({ - "path": getUrlPath(requestModel.url), + "path": uri.path, "method": requestModel.method.name.replaceRange( 0, 1, diff --git a/lib/utils/http_utils.dart b/lib/utils/http_utils.dart index 1b86dfb1..63aa6181 100644 --- a/lib/utils/http_utils.dart +++ b/lib/utils/http_utils.dart @@ -160,13 +160,3 @@ String? formatBody(String? body, MediaType? mediaType) { } return null; } - -String getBaseUrl(String url) { - Uri uri = Uri.parse(url); - return "${uri.scheme}://${uri.host}${uri.hasPort ? ":${uri.port}" : ""}${uri.hasFragment ? "#${uri.fragment}" : ""}"; -} - -String getUrlPath(String url) { - Uri uri = Uri.parse(url); - return uri.path; -} From 15c573d181549a933edddcbe71de7e561bef2b4d Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Tue, 26 Mar 2024 04:06:42 +0100 Subject: [PATCH 062/138] Update http client usage in request http service --- lib/providers/collection_providers.dart | 20 +++++++++++++------- lib/services/http_service.dart | 22 +++++++++++++--------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 75e9d7c5..10545f3a 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -1,11 +1,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'settings_providers.dart'; -import 'ui_providers.dart'; +import 'package:http/http.dart' as http; + +import '../consts.dart'; import '../models/models.dart'; import '../services/services.dart' show hiveHandler, HiveHandler, request; import '../utils/utils.dart' show getNewUuid, collectionToHAR; -import '../consts.dart'; -import 'package:http/http.dart' as http; +import 'settings_providers.dart'; +import 'ui_providers.dart'; final selectedIdStateProvider = StateProvider((ref) => null); @@ -24,13 +25,16 @@ final requestSequenceProvider = StateProvider>((ref) { return ids ?? []; }); +final client = http.Client(); + final StateNotifierProvider?> - collectionStateNotifierProvider = - StateNotifierProvider((ref) => CollectionStateNotifier(ref, hiveHandler)); + collectionStateNotifierProvider = StateNotifierProvider( + (ref) => CollectionStateNotifier(ref, hiveHandler, client)); class CollectionStateNotifier extends StateNotifier?> { - CollectionStateNotifier(this.ref, this.hiveHandler) : super(null) { + CollectionStateNotifier(this.ref, this.hiveHandler, this.httpClient) + : super(null) { var status = loadData(); Future.microtask(() { if (status) { @@ -46,6 +50,7 @@ class CollectionStateNotifier final Ref ref; final HiveHandler hiveHandler; final baseResponseModel = const ResponseModel(); + final http.Client httpClient; bool hasId(String id) => state?.keys.contains(id) ?? false; @@ -187,6 +192,7 @@ class CollectionStateNotifier (http.Response?, Duration?, String?)? responseRec = await request( requestModel, defaultUriScheme: defaultUriScheme, + client: httpClient, ); late final RequestModel newRequestModel; if (responseRec.$1 == null) { diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index dec0b516..9eb9228e 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -1,14 +1,16 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'package:http/http.dart' as http; -import 'package:apidash/utils/utils.dart'; -import 'package:apidash/models/models.dart'; + import 'package:apidash/consts.dart'; +import 'package:apidash/models/models.dart'; +import 'package:apidash/utils/utils.dart'; +import 'package:http/http.dart' as http; Future<(http.Response?, Duration?, String?)> request( RequestModel requestModel, { String defaultUriScheme = kDefaultUriScheme, + required http.Client client, }) async { (Uri?, String?) uriRec = getValidRequestUri( requestModel.url, @@ -66,23 +68,25 @@ Future<(http.Response?, Duration?, String?)> request( } switch (requestModel.method) { case HTTPVerb.get: - response = await http.get(requestUrl, headers: headers); + response = await client.get(requestUrl, headers: headers); break; case HTTPVerb.head: - response = await http.head(requestUrl, headers: headers); + response = await client.head(requestUrl, headers: headers); break; case HTTPVerb.post: - response = await http.post(requestUrl, headers: headers, body: body); + response = + await client.post(requestUrl, headers: headers, body: body); break; case HTTPVerb.put: - response = await http.put(requestUrl, headers: headers, body: body); + response = await client.put(requestUrl, headers: headers, body: body); break; case HTTPVerb.patch: - response = await http.patch(requestUrl, headers: headers, body: body); + response = + await client.patch(requestUrl, headers: headers, body: body); break; case HTTPVerb.delete: response = - await http.delete(requestUrl, headers: headers, body: body); + await client.delete(requestUrl, headers: headers, body: body); break; } stopwatch.stop(); From 3fa3076790cd1c3c1b3cd8607097b9ff990ac269 Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Tue, 26 Mar 2024 04:08:13 +0100 Subject: [PATCH 063/138] Add some tests for codePaneVisibleStateProvider I added some tests for the value of this provider by state injection. Still working on tests for interaction, value persistence across rebuilds and proper disposal of this provider. --- test/providers/ui_providers_test.dart | 150 ++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index 9d34619d..a68fbfec 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -3,14 +3,23 @@ import 'dart:io'; import 'package:apidash/providers/providers.dart'; import 'package:apidash/screens/dashboard.dart'; import 'package:apidash/screens/home_page/collection_pane.dart'; +import 'package:apidash/screens/home_page/editor_pane/details_card/code_pane.dart'; +import 'package:apidash/screens/home_page/editor_pane/details_card/response_pane.dart'; +import 'package:apidash/screens/home_page/editor_pane/editor_default.dart'; +import 'package:apidash/screens/home_page/editor_pane/editor_pane.dart'; +import 'package:apidash/screens/home_page/editor_pane/url_card.dart'; import 'package:apidash/screens/home_page/home_page.dart'; import 'package:apidash/screens/intro_page.dart'; import 'package:apidash/screens/settings_page.dart'; import 'package:apidash/services/hive_services.dart'; +import 'package:apidash/widgets/response_widgets.dart'; +import 'package:apidash/widgets/textfields.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:http/http.dart' as http; +import 'package:http/testing.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -336,4 +345,145 @@ void main() { expect(isDisposed, true); }); }); + + group('Testing codePaneVisibleStateProvider', () { + testWidgets("It should have have an initial value of false", + (tester) async { + // Mock the http client to return a 200 response + final mockClient = MockClient((request) async { + return http.Response('{"countries": "codes"}', 200); + }); + + await tester.pumpWidget( + ProviderScope( + overrides: [ + collectionStateNotifierProvider.overrideWith( + (ref) => CollectionStateNotifier(ref, hiveHandler, mockClient), + ) + ], + child: const MaterialApp( + home: RequestEditorPane(), + ), + ), + ); + + // Verify that the initial value is false + final editorPane = tester.element(find.byType(RequestEditorPane)); + final container = ProviderScope.containerOf(editorPane); + expect(container.read(codePaneVisibleStateProvider), false); + }); + + testWidgets("When state is false ResponsePane should be visible", + (tester) async { + // Mock the http client to return a 200 response + final mockClient = MockClient((request) async { + return http.Response('{"countries": "codes"}', 200); + }); + + await tester.pumpWidget( + ProviderScope( + overrides: [ + collectionStateNotifierProvider.overrideWith( + (ref) => CollectionStateNotifier(ref, hiveHandler, mockClient), + ) + ], + child: const MaterialApp( + home: RequestEditorPane(), + ), + ), + ); + + expect(find.byType(RequestEditorDefault), findsOneWidget); + + // Tap on the "Plus New" button + Finder plusNewButton = find.descendant( + of: find.byType(RequestEditorDefault), + matching: find.byType(ElevatedButton), + ); + await tester.tap(plusNewButton); + await tester.pump(); + + // Verify that NotSentWidget is visible + expect(find.byType(NotSentWidget), findsOneWidget); + + // Add some data in URLTextField + Finder field = find.descendant( + of: find.byType(URLField), + matching: find.byType(TextFormField), + ); + const url = 'https://api.foss42.com/country/codes'; + await tester.enterText(field, url); + await tester.pump(); + + // Tap on the "Send" button + Finder sendButton = find.byType(SendButton); + await tester.tap(sendButton); + await tester.pump(); + + final editorPane = tester.element(find.byType(RequestEditorPane)); + final container = ProviderScope.containerOf(editorPane); + expect(container.read(codePaneVisibleStateProvider), false); + expect(find.byType(ResponsePane), findsOneWidget); + }); + + testWidgets("When state is true CodePane should be visible", + (tester) async { + // Mock the http client to return a 200 response + final mockClient = MockClient((request) async { + return http.Response('{"countries": "codes"}', 200); + }); + + await tester.pumpWidget( + ProviderScope( + overrides: [ + collectionStateNotifierProvider.overrideWith( + (ref) => CollectionStateNotifier(ref, hiveHandler, mockClient), + ) + ], + child: const MaterialApp( + home: Scaffold( + body: RequestEditorPane(), + ), + ), + ), + ); + + expect(find.byType(RequestEditorDefault), findsOneWidget); + + // Tap on the "Plus New" button + Finder plusNewButton = find.descendant( + of: find.byType(RequestEditorDefault), + matching: find.byType(ElevatedButton), + ); + await tester.tap(plusNewButton); + await tester.pump(); + + // Verify that NotSentWidget is visible + expect(find.byType(NotSentWidget), findsOneWidget); + + // Add some data in URLTextField + Finder field = find.descendant( + of: find.byType(URLField), + matching: find.byType(TextFormField), + ); + const url = 'https://api.foss42.com/country/codes'; + await tester.enterText(field, url); + await tester.pump(); + + // Tap on the "Send" button + Finder sendButton = find.byType(SendButton); + await tester.tap(sendButton); + await tester.pump(); + + final editorPane = tester.element(find.byType(RequestEditorPane)); + final container = ProviderScope.containerOf(editorPane); + // Change codePaneVisibleStateProvider state to true + container.read(codePaneVisibleStateProvider.notifier).state = true; + await tester.pump(); + + // Verify that the CodePane is visible + expect(container.read(codePaneVisibleStateProvider), true); + expect(find.byType(CodePane), findsOneWidget); + }); + }); } From 017bc4f1085181c0c42e1b3b52d21c78d948bf4a Mon Sep 17 00:00:00 2001 From: Yashas H Majmudar Date: Wed, 27 Mar 2024 22:06:32 +0530 Subject: [PATCH 064/138] fix: prompt only when changes made --- lib/app.dart | 2 +- lib/providers/collection_providers.dart | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index f60198af..caae2729 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -57,7 +57,7 @@ class _AppState extends ConsumerState with WindowListener { bool isPreventClose = await windowManager.isPreventClose(); if (isPreventClose) { if (ref.watch( - settingsProvider.select((value) => value.promptBeforeClosing))) { + settingsProvider.select((value) => value.promptBeforeClosing)) && ref.watch(collectionStateNotifierProvider.notifier).changed) { showDialog( context: context, builder: (_) => AlertDialog( diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 75e9d7c5..efe93967 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -1,11 +1,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'settings_providers.dart'; -import 'ui_providers.dart'; +import 'package:http/http.dart' as http; + +import '../consts.dart'; import '../models/models.dart'; import '../services/services.dart' show hiveHandler, HiveHandler, request; import '../utils/utils.dart' show getNewUuid, collectionToHAR; -import '../consts.dart'; -import 'package:http/http.dart' as http; +import 'settings_providers.dart'; +import 'ui_providers.dart'; final selectedIdStateProvider = StateProvider((ref) => null); @@ -46,6 +47,7 @@ class CollectionStateNotifier final Ref ref; final HiveHandler hiveHandler; final baseResponseModel = const ResponseModel(); + bool changed = false; bool hasId(String id) => state?.keys.contains(id) ?? false; @@ -61,6 +63,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newRequestModel; state = map; + changed = true; ref .read(requestSequenceProvider.notifier) .update((state) => [id, ...state]); @@ -94,6 +97,7 @@ class CollectionStateNotifier var map = {...state!}; map.remove(id); state = map; + changed = true; } void clearResponse(String? id) { @@ -107,6 +111,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newModel; state = map; + changed = true; } void duplicate(String id) { @@ -123,6 +128,7 @@ class CollectionStateNotifier var map = {...state!}; map[newId] = newModel; state = map; + changed = true; ref.read(requestSequenceProvider.notifier).state = [...itemIds]; ref.read(selectedIdStateProvider.notifier).state = newId; @@ -167,6 +173,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newModel; state = map; + changed = true; } Future sendRequest(String id) async { @@ -183,6 +190,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = requestModel.copyWith(isWorking: true); state = map; + changed = true; (http.Response?, Duration?, String?)? responseRec = await request( requestModel, @@ -213,6 +221,7 @@ class CollectionStateNotifier map = {...state!}; map[id] = newRequestModel; state = map; + changed = true; } Future clearData() async { @@ -222,6 +231,7 @@ class CollectionStateNotifier ref.read(clearDataStateProvider.notifier).state = false; ref.read(requestSequenceProvider.notifier).state = []; state = {}; + changed = true; } bool loadData() { From 0c04ff3343628a63916bc26f88d55975d796ce9f Mon Sep 17 00:00:00 2001 From: Yashas H Majmudar Date: Wed, 27 Mar 2024 22:10:11 +0530 Subject: [PATCH 065/138] fix: prompt when changes made to reorder --- lib/providers/collection_providers.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index efe93967..6c3f1411 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -75,6 +75,7 @@ class CollectionStateNotifier final itemId = itemIds.removeAt(oldIdx); itemIds.insert(newIdx, itemId); ref.read(requestSequenceProvider.notifier).state = [...itemIds]; + changed = true; } void remove(String id) { From e449ced99b0347059771e6be00746b4399d702ae Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:51:41 +0530 Subject: [PATCH 066/138] added ruby faraday as constant --- lib/consts.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/consts.dart b/lib/consts.dart index 2ad9d185..191eb938 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -289,6 +289,7 @@ enum CodegenLanguage { kotlinOkHttp("Kotlin (okhttp3)", "java", "kt"), pythonRequests("Python (requests)", "python", "py"), pythonHttpClient("Python (http.client)", "python", "py"), + rubyFaraday("Ruby (faraday)", "ruby", "rb"), rustActix("Rust (Actix Client)", "rust", "rs"), rustReqwest("Rust (reqwest)", "rust", "rs"), rustCurl("Rust (curl-rust)", "rust", "rs"), From d9b38a0255a98b70f637efd7103d68f98c5eecc6 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:51:54 +0530 Subject: [PATCH 067/138] added support for ruby faraday --- lib/codegen/codegen.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index f3f606ae..43f3b346 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -8,6 +8,7 @@ import 'kotlin/okhttp.dart'; import 'php/guzzle.dart'; import 'python/http_client.dart'; import 'python/requests.dart'; +import 'ruby/faraday.dart'; import 'rust/actix.dart'; import 'rust/curl_rust.dart'; import 'rust/reqwest.dart'; @@ -72,6 +73,9 @@ class Codegen { .getCode(rM, boundary: boundary ?? getNewUuid()); case CodegenLanguage.pythonRequests: return PythonRequestsCodeGen().getCode(rM, boundary: boundary); + case CodegenLanguage.rubyFaraday: + return RubyFaradayCodeGen() + .getCode(rM, boundary: boundary ?? getNewUuid()); case CodegenLanguage.rustActix: return RustActixCodeGen().getCode(rM, boundary: boundary); case CodegenLanguage.rustCurl: From 5b57ae46ff06c289aba87b59948d2edd3c768bfb Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:52:31 +0530 Subject: [PATCH 068/138] added class for faraday codegen --- lib/codegen/ruby/faraday.dart | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 lib/codegen/ruby/faraday.dart diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart new file mode 100644 index 00000000..a01c0719 --- /dev/null +++ b/lib/codegen/ruby/faraday.dart @@ -0,0 +1,14 @@ +import 'package:apidash/consts.dart'; +import 'package:jinja/jinja.dart' as jj; +import 'package:apidash/utils/utils.dart' show getValidRequestUri; +import 'package:apidash/utils/http_utils.dart' show stripUriParams; + +import 'package:apidash/models/models.dart' show RequestModel; + +// Note that delete is a special case in Faraday as API Dash supports request +// body inside delete reqest, but Faraday does not. Hence we need to manually +// setup request body for delete request and add that to request. +// +// Refer https://lostisland.github.io/faraday/#/getting-started/quick-start?id=get-head-delete-trace +class RubyFaradayCodeGen { +} From 642fca1cf656ba61ac2182a5b0e185b3b62a8863 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:53:07 +0530 Subject: [PATCH 069/138] added require templates --- lib/codegen/ruby/faraday.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index a01c0719..7887be9c 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -11,4 +11,13 @@ import 'package:apidash/models/models.dart' show RequestModel; // // Refer https://lostisland.github.io/faraday/#/getting-started/quick-start?id=get-head-delete-trace class RubyFaradayCodeGen { + + final String kStringFaradayRequireStatement = """ +require 'uri' +require 'faraday' +"""; + + final String kStringFaradayMultipartRequireStatement = ''' +require 'faraday/multipart' +'''; } From 402670619ceb399a66a62ffa1b1dfe982ea70110 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:53:33 +0530 Subject: [PATCH 070/138] added request url template --- lib/codegen/ruby/faraday.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index 7887be9c..35d57c4d 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -20,4 +20,9 @@ require 'faraday' final String kStringFaradayMultipartRequireStatement = ''' require 'faraday/multipart' '''; + + final String kTemplateRequestUrl = """ +\nREQUEST_URL = URI("{{ url }}")\n\n +"""; + } From cf3ff17580732863fdf0b47fd6b6f404dda36980 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:53:56 +0530 Subject: [PATCH 071/138] added request body payload templates --- lib/codegen/ruby/faraday.dart | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index 35d57c4d..b59fc6a2 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -23,6 +23,23 @@ require 'faraday/multipart' final String kTemplateRequestUrl = """ \nREQUEST_URL = URI("{{ url }}")\n\n +"""; + + final String kTemplateBody = """ +PAYLOAD = <<-{{ boundary }} +{{ body }} +{{ boundary }}\n\n +"""; + + final String kTemplateFormParamsWithFile = """ +PAYLOAD = { +{% for param in params %}{% if param.type == "text" %} "{{ param.name }}" => Faraday::Multipart::ParamPart.new("{{ param.value }}", "text/plain"), +{% elif param.type == "file" %} "{{ param.name }}" => Faraday::Multipart::FilePart.new("{{ param.value }}", "application/octet-stream"),{% endif %}{% endfor %} +}\n\n +"""; + + final String kTemplateFormParamsWithoutFile = """ +PAYLOAD = URI.encode_www_form({\n{% for param in params %} "{{ param.name }}" => "{{ param.value }}",\n{% endfor %}})\n\n """; } From 923310208313d736fd62bf8ffea9a925b2df0631 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:54:18 +0530 Subject: [PATCH 072/138] connection creation template --- lib/codegen/ruby/faraday.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index b59fc6a2..0f4d346a 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -40,6 +40,12 @@ PAYLOAD = { final String kTemplateFormParamsWithoutFile = """ PAYLOAD = URI.encode_www_form({\n{% for param in params %} "{{ param.name }}" => "{{ param.value }}",\n{% endfor %}})\n\n +"""; + + final String kTemplateConnection = """ +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter{% if hasFile %}\n faraday.request :multipart{% endif %} +end\n\n """; } From f175483d865e0fd92acff95709da92a5a366f4f4 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:56:03 +0530 Subject: [PATCH 073/138] connection response internal templates --- lib/codegen/ruby/faraday.dart | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index 0f4d346a..285c4edd 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -46,6 +46,30 @@ PAYLOAD = URI.encode_www_form({\n{% for param in params %} "{{ param.name }}" = conn = Faraday.new do |faraday| faraday.adapter Faraday.default_adapter{% if hasFile %}\n faraday.request :multipart{% endif %} end\n\n +"""; + + final String kTemplateRequestStart = """ +response = conn.{{ method|lower }}(REQUEST_URL{% if doesMethodAcceptBody and containsBody %}, PAYLOAD{% endif %}) do |req|\n +"""; + + final String kTemplateRequestOptionsBoundary = """ + req.options.boundary = "{{ boundary }}"\n +"""; + + final String kTemplateRequestParams = """ + req.params = {\n{% for key, val in params %} "{{ key }}" => "{{ val }}",\n{% endfor %} }\n +"""; + + final String kTemplateRequestHeaders = """ + req.headers = {\n{% for key, val in headers %} "{{ key }}" => "{{ val }}",\n{% endfor %} }\n +"""; + + final String kStringDeleteRequestBody = """ + req.body = PAYLOAD +"""; + + final String kStringRequestEnd = """ +end\n """; } From 73e087a257b7f792de0be336f2238f53ef9ee443 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:56:27 +0530 Subject: [PATCH 074/138] response displaying template --- lib/codegen/ruby/faraday.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index 285c4edd..f5486c18 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -72,4 +72,8 @@ response = conn.{{ method|lower }}(REQUEST_URL{% if doesMethodAcceptBody and con end\n """; + final String kStringResponse = """ +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; } From 5774db422fef32eb59ea1e8a064159d0187898c1 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:57:07 +0530 Subject: [PATCH 075/138] added getCode function --- lib/codegen/ruby/faraday.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index f5486c18..4fe1c7f3 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -76,4 +76,10 @@ end\n puts "Status Code: #{response.status}" puts "Response Body: #{response.body}" """; + + String? getCode( + RequestModel requestModel, { + String? boundary, + }) { + } } From 3b93bb3f8602916aa04fd9c4e5c226dbe6b7f262 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:57:46 +0530 Subject: [PATCH 076/138] try catch block for error handling --- lib/codegen/ruby/faraday.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index 4fe1c7f3..319e83c6 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -81,5 +81,10 @@ puts "Response Body: #{response.body}" RequestModel requestModel, { String? boundary, }) { + try { + String result = ""; + } catch (e) { + return null; + } } } From 0150675f9fe717b0f95c87dbe8e23b82bf3b94b6 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:58:55 +0530 Subject: [PATCH 077/138] custom boundary creation for heredoc --- lib/codegen/ruby/faraday.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index 319e83c6..cc6b21aa 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -83,6 +83,13 @@ puts "Response Body: #{response.body}" }) { try { String result = ""; + + if (boundary != null) { + // boundary needs to start with a character, hence we append apidash + // and remove hyphen characters from the existing boundary + boundary = "apidash_${boundary.replaceAll(RegExp("-"), "")}"; + } + } catch (e) { return null; } From 21e05c288e640f0576a5236bb296dc08550804be Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 03:59:18 +0530 Subject: [PATCH 078/138] setting up request url --- lib/codegen/ruby/faraday.dart | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index cc6b21aa..b8c8750a 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -90,6 +90,27 @@ puts "Response Body: #{response.body}" boundary = "apidash_${boundary.replaceAll(RegExp("-"), "")}"; } + var rec = getValidRequestUri( + requestModel.url, + requestModel.enabledRequestParams, + ); + + Uri? uri = rec.$1; + + if (uri == null) { + return ""; + } + + var url = stripUriParams(uri); + + result += kStringFaradayRequireStatement; + if (requestModel.hasFormDataContentType && requestModel.hasFileInFormData) { + result += kStringFaradayMultipartRequireStatement; + } + + var templateRequestUrl = jj.Template(kTemplateRequestUrl); + result += templateRequestUrl.render({"url": url}); + } catch (e) { return null; } From 7e43c3356572df019f6cd99b5860dedae9ed1f42 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 04:00:06 +0530 Subject: [PATCH 079/138] payload creation --- lib/codegen/ruby/faraday.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index b8c8750a..f44db9cc 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -111,6 +111,22 @@ puts "Response Body: #{response.body}" var templateRequestUrl = jj.Template(kTemplateRequestUrl); result += templateRequestUrl.render({"url": url}); + if (requestModel.hasFormData) { + jj.Template payload; + if (requestModel.hasFileInFormData) { + payload = jj.Template(kTemplateFormParamsWithFile); + } else { + payload = jj.Template(kTemplateFormParamsWithoutFile); + } + result += payload.render({"params": requestModel.formDataMapList}); + } else if (requestModel.hasJsonData || requestModel.hasTextData) { + var templateBody = jj.Template(kTemplateBody); + result += templateBody.render({ + "body": requestModel.requestBody, // + "boundary": boundary, + }); + } + } catch (e) { return null; } From c9c51a284026b0fef4d6befe10144ade0af1edb9 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 04:00:23 +0530 Subject: [PATCH 080/138] faraday connection creation --- lib/codegen/ruby/faraday.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index f44db9cc..be0d5375 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -127,6 +127,11 @@ puts "Response Body: #{response.body}" }); } + // crreating faraday connection for request + var templateConnection = jj.Template(kTemplateConnection); + result += templateConnection.render({ + "hasFile": requestModel.hasFormDataContentType && requestModel.hasFileInFormData // + }); } catch (e) { return null; } From 261103d5eb92220af632e6ffcae3abdc980ef422 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 04:00:50 +0530 Subject: [PATCH 081/138] request sending setup --- lib/codegen/ruby/faraday.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index be0d5375..8018702c 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -132,6 +132,21 @@ puts "Response Body: #{response.body}" result += templateConnection.render({ "hasFile": requestModel.hasFormDataContentType && requestModel.hasFileInFormData // }); + + // start of the request sending + var templateRequestStart = jj.Template(kTemplateRequestStart); + result += templateRequestStart.render({ + "method": requestModel.method.name, // + "doesMethodAcceptBody": + kMethodsWithBody.contains(requestModel.method) && requestModel.method != HTTPVerb.delete, // + "containsBody": requestModel.hasBody, // + }); + + if (requestModel.hasFormDataContentType && requestModel.hasFileInFormData) { + var templateRequestOptionsBoundary = jj.Template(kTemplateRequestOptionsBoundary); + result += templateRequestOptionsBoundary.render({"boundary": boundary}); + } + } catch (e) { return null; } From 0354792457696a08b589441d287bb4a21d63582a Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 04:01:03 +0530 Subject: [PATCH 082/138] inclusion of headers --- lib/codegen/ruby/faraday.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index 8018702c..f05fbac2 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -147,6 +147,21 @@ puts "Response Body: #{response.body}" result += templateRequestOptionsBoundary.render({"boundary": boundary}); } + var headers = requestModel.enabledHeadersMap; + if (requestModel.hasBody && !requestModel.hasContentTypeHeader) { + if (requestModel.hasJsonData || requestModel.hasTextData) { + headers["Content-Type"] = requestModel.requestBodyContentType.header; + } else if (requestModel.hasFormData) { + headers["Content-Type"] = + (requestModel.hasFileInFormData) ? "multipart/form-data" : "application/x-www-form-urlencoded"; + } + } + + if (headers.isNotEmpty) { + var templateRequestHeaders = jj.Template(kTemplateRequestHeaders); + result += templateRequestHeaders.render({"headers": headers}); + } + } catch (e) { return null; } From 53ef0ce7474e396a70d9cd45a7479f9a54201185 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 04:01:19 +0530 Subject: [PATCH 083/138] including uri parameters --- lib/codegen/ruby/faraday.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index f05fbac2..8357ee03 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -162,6 +162,21 @@ puts "Response Body: #{response.body}" result += templateRequestHeaders.render({"headers": headers}); } + if (uri.hasQuery) { + var params = uri.queryParameters; + if (params.isNotEmpty) { + var templateRequestParams = jj.Template(kTemplateRequestParams); + result += templateRequestParams.render({"params": params}); + } + } + + if (requestModel.hasBody && requestModel.method == HTTPVerb.delete) { + result += kStringDeleteRequestBody; + } + + result += kStringRequestEnd; + result += kStringResponse; + return result; } catch (e) { return null; } From e970aa1cc37f5c0e93337bb02123036c7fff1604 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Thu, 28 Mar 2024 04:19:22 +0530 Subject: [PATCH 084/138] added test for ruby faraday codegen --- test/codegen/ruby_faraday_codegen_test.dart | 744 ++++++++++++++++++++ 1 file changed, 744 insertions(+) create mode 100644 test/codegen/ruby_faraday_codegen_test.dart diff --git a/test/codegen/ruby_faraday_codegen_test.dart b/test/codegen/ruby_faraday_codegen_test.dart new file mode 100644 index 00000000..5f94080c --- /dev/null +++ b/test/codegen/ruby_faraday_codegen_test.dart @@ -0,0 +1,744 @@ +import 'package:apidash/codegen/codegen.dart'; +import 'package:apidash/consts.dart'; +import 'package:test/test.dart'; +import '../request_models.dart'; + +void main() { + final codeGen = Codegen(); + + group('GET Request', () { + test('GET 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet1, "https"), expectedCode); + }); + + test('GET 2', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/country/data") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.params = { + "code" => "US", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet2, "https"), expectedCode); + }); + + test('GET 3', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/country/data") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.params = { + "code" => "IND", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet3, "https"), expectedCode); + }); + + test('GET 4', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/humanize/social") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.params = { + "num" => "8700000", + "digits" => "3", + "system" => "SS", + "add_space" => "true", + "trailing_zeros" => "true", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet4, "https"), expectedCode); + }); + + test('GET 5', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.headers = { + "User-Agent" => "Test Agent", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet5, "https"), expectedCode); + }); + + test('GET 6', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.headers = { + "User-Agent" => "Test Agent", + } + req.params = { + "raw" => "true", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet6, "https"), expectedCode); + }); + + test('GET 7', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet7, "https"), expectedCode); + }); + + test('GET 8', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.headers = { + "User-Agent" => "Test Agent", + } + req.params = { + "raw" => "true", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet8, "https"), expectedCode); + }); + + test('GET 9', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/humanize/social") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.params = { + "num" => "8700000", + "add_space" => "true", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet9, "https"), expectedCode); + }); + + test('GET 10', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/humanize/social") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.headers = { + "User-Agent" => "Test Agent", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode( + CodegenLanguage.rubyFaraday, + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/humanize/social") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.headers = { + "User-Agent" => "Test Agent", + } + req.params = { + "num" => "8700000", + "digits" => "3", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet11, "https"), expectedCode); + }); + + test('GET 12', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/humanize/social") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet12, "https"), expectedCode); + }); + }); + + group('HEAD Request', () { + test('HEAD 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.head(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelHead1, "https"), expectedCode); + }); + + test('HEAD 2', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("http://api.apidash.dev") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.head(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelHead2, "http"), expectedCode); + }); + }); + + group('POST Request', () { + test('POST 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/case/lower") + +PAYLOAD = <<-apidash_a5d7a5d09d721f398905c39274c7fa33 +{ +"text": "I LOVE Flutter" +} +apidash_a5d7a5d09d721f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "text/plain", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost1, "https", + boundary: "a5d7a5d09d721f398905c39274c7fa33"), + expectedCode); + }); + + test('POST 2', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/case/lower") + +PAYLOAD = <<-apidash_8b9b12a09dc81f398905c39274c7fa33 +{ +"text": "I LOVE Flutter", +"flag": null, +"male": true, +"female": false, +"no": 1.2, +"arr": ["null", "true", "false", null] +} +apidash_8b9b12a09dc81f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "application/json", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost2, "https", + boundary: "8b9b12a09dc81f398905c39274c7fa33"), + expectedCode); + }); + + test('POST 3', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/case/lower") + +PAYLOAD = <<-apidash_5c3b98809e3c1f398905c39274c7fa33 +{ +"text": "I LOVE Flutter" +} +apidash_5c3b98809e3c1f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "User-Agent" => "Test Agent", + "Content-Type" => "application/json", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost3, "https", + boundary: "5c3b98809e3c1f398905c39274c7fa33"), + expectedCode); + }); + + test('POST 4', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/io/form") + +PAYLOAD = URI.encode_www_form({ + "text" => "API", + "sep" => "|", + "times" => "3", +}) + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "application/x-www-form-urlencoded", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode( + CodegenLanguage.rubyFaraday, + requestModelPost4, + "https", + ), + expectedCode); + }); + test('POST 5', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/io/form") + +PAYLOAD = URI.encode_www_form({ + "text" => "API", + "sep" => "|", + "times" => "3", +}) + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "User-Agent" => "Test Agent", + "Content-Type" => "application/x-www-form-urlencoded", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost5, "https", boundary: "test"), expectedCode); + }); + test('POST 6', () { + const expectedCode = r"""require 'uri' +require 'faraday' +require 'faraday/multipart' + +REQUEST_URL = URI("https://api.apidash.dev/io/img") + +PAYLOAD = { + "token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"), + "imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"), +} + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter + faraday.request :multipart +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.options.boundary = "apidash_6f6629609fb41f398905c39274c7fa33" + req.headers = { + "Content-Type" => "multipart/form-data", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost6, "https", + boundary: "6f6629609fb41f398905c39274c7fa33"), + expectedCode); + }); + test('POST 7', () { + const expectedCode = r"""require 'uri' +require 'faraday' +require 'faraday/multipart' + +REQUEST_URL = URI("https://api.apidash.dev/io/img") + +PAYLOAD = { + "token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"), + "imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"), +} + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter + faraday.request :multipart +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.options.boundary = "apidash_3955fcc0a0b71f398905c39274c7fa33" + req.headers = { + "Content-Type" => "multipart/form-data", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost7, "https", + boundary: "3955fcc0a0b71f398905c39274c7fa33"), + expectedCode); + }); + test('POST 8', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/io/form") + +PAYLOAD = URI.encode_www_form({ + "text" => "API", + "sep" => "|", + "times" => "3", +}) + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "application/x-www-form-urlencoded", + } + req.params = { + "size" => "2", + "len" => "3", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost8, "https", boundary: "test"), expectedCode); + }); + test('POST 9', () { + const expectedCode = r"""require 'uri' +require 'faraday' +require 'faraday/multipart' + +REQUEST_URL = URI("https://api.apidash.dev/io/img") + +PAYLOAD = { + "token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"), + "imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"), +} + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter + faraday.request :multipart +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.options.boundary = "apidash_599e5a20a1361f398905c39274c7fa33" + req.headers = { + "User-Agent" => "Test Agent", + "Keep-Alive" => "true", + "Content-Type" => "multipart/form-data", + } + req.params = { + "size" => "2", + "len" => "3", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost9, "https", + boundary: "599e5a20a1361f398905c39274c7fa33"), + expectedCode); + }); + }); + + group('PUT Request', () { + test('PUT 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://reqres.in/api/users/2") + +PAYLOAD = <<-apidash_b4e90990a34b1f398905c39274c7fa33 +{ +"name": "morpheus", +"job": "zion resident" +} +apidash_b4e90990a34b1f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.put(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "application/json", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPut1, "https", + boundary: "b4e90990a34b1f398905c39274c7fa33"), + expectedCode); + }); + }); + + group('PATCH Request', () { + test('PATCH 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://reqres.in/api/users/2") + +PAYLOAD = <<-apidash_b2e9a260a3931f398905c39274c7fa33 +{ +"name": "marfeus", +"job": "accountant" +} +apidash_b2e9a260a3931f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.patch(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "application/json", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPatch1, "https", + boundary: "b2e9a260a3931f398905c39274c7fa33"), + expectedCode); + }); + }); + + group('DELETE Request', () { + test('DELETE 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://reqres.in/api/users/2") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.delete(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelDelete1, "https"), expectedCode); + }); + + test('DELETE 2', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://reqres.in/api/users/2") + +PAYLOAD = <<-apidash_f2291be0a40b1f398905c39274c7fa33 +{ +"name": "marfeus", +"job": "accountant" +} +apidash_f2291be0a40b1f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.delete(REQUEST_URL) do |req| + req.headers = { + "Content-Type" => "application/json", + } + req.body = PAYLOAD +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelDelete2, "https", + boundary: "f2291be0a40b1f398905c39274c7fa33"), + expectedCode); + }); + }); +} From 51911e4b0a452c529f471399f6d46f7ebb3a1398 Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Thu, 28 Mar 2024 02:22:51 +0100 Subject: [PATCH 085/138] Remove request mocks I am now sending actual requests as adviced by @ashitaprasad since the APIs are maintained by us --- lib/providers/collection_providers.dart | 11 ++----- lib/services/http_service.dart | 15 ++++----- test/providers/ui_providers_test.dart | 44 ++++--------------------- 3 files changed, 15 insertions(+), 55 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 10545f3a..e55ab8bd 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -25,16 +25,13 @@ final requestSequenceProvider = StateProvider>((ref) { return ids ?? []; }); -final client = http.Client(); - final StateNotifierProvider?> - collectionStateNotifierProvider = StateNotifierProvider( - (ref) => CollectionStateNotifier(ref, hiveHandler, client)); + collectionStateNotifierProvider = + StateNotifierProvider((ref) => CollectionStateNotifier(ref, hiveHandler)); class CollectionStateNotifier extends StateNotifier?> { - CollectionStateNotifier(this.ref, this.hiveHandler, this.httpClient) - : super(null) { + CollectionStateNotifier(this.ref, this.hiveHandler) : super(null) { var status = loadData(); Future.microtask(() { if (status) { @@ -50,7 +47,6 @@ class CollectionStateNotifier final Ref ref; final HiveHandler hiveHandler; final baseResponseModel = const ResponseModel(); - final http.Client httpClient; bool hasId(String id) => state?.keys.contains(id) ?? false; @@ -192,7 +188,6 @@ class CollectionStateNotifier (http.Response?, Duration?, String?)? responseRec = await request( requestModel, defaultUriScheme: defaultUriScheme, - client: httpClient, ); late final RequestModel newRequestModel; if (responseRec.$1 == null) { diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 9eb9228e..35a45e36 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -10,7 +10,6 @@ import 'package:http/http.dart' as http; Future<(http.Response?, Duration?, String?)> request( RequestModel requestModel, { String defaultUriScheme = kDefaultUriScheme, - required http.Client client, }) async { (Uri?, String?) uriRec = getValidRequestUri( requestModel.url, @@ -68,25 +67,23 @@ Future<(http.Response?, Duration?, String?)> request( } switch (requestModel.method) { case HTTPVerb.get: - response = await client.get(requestUrl, headers: headers); + response = await http.get(requestUrl, headers: headers); break; case HTTPVerb.head: - response = await client.head(requestUrl, headers: headers); + response = await http.head(requestUrl, headers: headers); break; case HTTPVerb.post: - response = - await client.post(requestUrl, headers: headers, body: body); + response = await http.post(requestUrl, headers: headers, body: body); break; case HTTPVerb.put: - response = await client.put(requestUrl, headers: headers, body: body); + response = await http.put(requestUrl, headers: headers, body: body); break; case HTTPVerb.patch: - response = - await client.patch(requestUrl, headers: headers, body: body); + response = await http.patch(requestUrl, headers: headers, body: body); break; case HTTPVerb.delete: response = - await client.delete(requestUrl, headers: headers, body: body); + await http.delete(requestUrl, headers: headers, body: body); break; } stopwatch.stop(); diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index a68fbfec..c6c66c6d 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -18,8 +18,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:http/http.dart' as http; -import 'package:http/testing.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -349,19 +347,9 @@ void main() { group('Testing codePaneVisibleStateProvider', () { testWidgets("It should have have an initial value of false", (tester) async { - // Mock the http client to return a 200 response - final mockClient = MockClient((request) async { - return http.Response('{"countries": "codes"}', 200); - }); - await tester.pumpWidget( - ProviderScope( - overrides: [ - collectionStateNotifierProvider.overrideWith( - (ref) => CollectionStateNotifier(ref, hiveHandler, mockClient), - ) - ], - child: const MaterialApp( + const ProviderScope( + child: MaterialApp( home: RequestEditorPane(), ), ), @@ -375,19 +363,9 @@ void main() { testWidgets("When state is false ResponsePane should be visible", (tester) async { - // Mock the http client to return a 200 response - final mockClient = MockClient((request) async { - return http.Response('{"countries": "codes"}', 200); - }); - await tester.pumpWidget( - ProviderScope( - overrides: [ - collectionStateNotifierProvider.overrideWith( - (ref) => CollectionStateNotifier(ref, hiveHandler, mockClient), - ) - ], - child: const MaterialApp( + const ProviderScope( + child: MaterialApp( home: RequestEditorPane(), ), ), @@ -428,19 +406,9 @@ void main() { testWidgets("When state is true CodePane should be visible", (tester) async { - // Mock the http client to return a 200 response - final mockClient = MockClient((request) async { - return http.Response('{"countries": "codes"}', 200); - }); - await tester.pumpWidget( - ProviderScope( - overrides: [ - collectionStateNotifierProvider.overrideWith( - (ref) => CollectionStateNotifier(ref, hiveHandler, mockClient), - ) - ], - child: const MaterialApp( + const ProviderScope( + child: MaterialApp( home: Scaffold( body: RequestEditorPane(), ), From 2700ade751d323f237b583e76a53a5a691f24cd4 Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Thu, 28 Mar 2024 02:52:23 +0100 Subject: [PATCH 086/138] Add more tests for codePaneVisibleStateProvider --- test/providers/ui_providers_test.dart | 159 ++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index c6c66c6d..1c4fde90 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -453,5 +453,164 @@ void main() { expect(container.read(codePaneVisibleStateProvider), true); expect(find.byType(CodePane), findsOneWidget); }); + + testWidgets("Hide/View Code button toggles the state", (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: Scaffold( + body: RequestEditorPane(), + ), + ), + ), + ); + + expect(find.byType(RequestEditorDefault), findsOneWidget); + + // Tap on the "Plus New" button + Finder plusNewButton = find.descendant( + of: find.byType(RequestEditorDefault), + matching: find.byType(ElevatedButton), + ); + await tester.tap(plusNewButton); + await tester.pump(); + + // Verify that NotSentWidget is visible + expect(find.byType(NotSentWidget), findsOneWidget); + + // Add some data in URLTextField + Finder field = find.descendant( + of: find.byType(URLField), + matching: find.byType(TextFormField), + ); + const url = 'https://api.foss42.com/country/codes'; + await tester.enterText(field, url); + await tester.pump(); + + // Tap on the "Send" button + Finder sendButton = find.byType(SendButton); + await tester.tap(sendButton); + await tester.pump(); + + final editorPane = tester.element(find.byType(RequestEditorPane)); + final container = ProviderScope.containerOf(editorPane); + final bool currentValue = container.read(codePaneVisibleStateProvider); + + // Click on View Code button + await tester.tap(find.byIcon(Icons.code_rounded)); + await tester.pump(); + + // Verify that the state value has changed + expect(container.read(codePaneVisibleStateProvider), !currentValue); + final bool newValue = container.read(codePaneVisibleStateProvider); + + // Click on Hide Code button + await tester.tap(find.byIcon(Icons.code_off_rounded)); + await tester.pump(); + + // Verify that the state value has changed + expect(container.read(codePaneVisibleStateProvider), !newValue); + }); + + testWidgets("That state persists across widget rebuilds", (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: Scaffold( + body: RequestEditorPane(), + ), + ), + ), + ); + + expect(find.byType(RequestEditorDefault), findsOneWidget); + + // Tap on the "Plus New" button + Finder plusNewButton = find.descendant( + of: find.byType(RequestEditorDefault), + matching: find.byType(ElevatedButton), + ); + await tester.tap(plusNewButton); + await tester.pump(); + + // Verify that NotSentWidget is visible + expect(find.byType(NotSentWidget), findsOneWidget); + + // Add some data in URLTextField + Finder field = find.descendant( + of: find.byType(URLField), + matching: find.byType(TextFormField), + ); + const url = 'https://api.foss42.com/country/codes'; + await tester.enterText(field, url); + await tester.pump(); + + // Tap on the "Send" button + Finder sendButton = find.byType(SendButton); + await tester.tap(sendButton); + await tester.pump(); + + final editorPane = tester.element(find.byType(RequestEditorPane)); + final container = ProviderScope.containerOf(editorPane); + final bool currentValue = container.read(codePaneVisibleStateProvider); + + // Click on View Code button + await tester.tap(find.byIcon(Icons.code_rounded)); + await tester.pump(); + + // Verify that the state value has changed + expect(container.read(codePaneVisibleStateProvider), !currentValue); + bool matcher = !currentValue; + + // Rebuild the widget tree + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: Scaffold( + body: RequestEditorPane(), + ), + ), + ), + ); + + // Verify that the value of codePaneVisibleStateProvider is still true + final containerAfterRebuild = ProviderScope.containerOf(editorPane); + bool actual = containerAfterRebuild.read(codePaneVisibleStateProvider); + expect(actual, matcher); + }); + + testWidgets("That it is properly disposed", (tester) async { + await tester.pumpWidget( + const ProviderScope( + child: MaterialApp( + home: Scaffold( + body: RequestEditorPane(), + ), + ), + ), + ); + + // Verify that codePaneVisibleStateProvider is present + final editorPane = tester.element(find.byType(RequestEditorPane)); + final container = ProviderScope.containerOf(editorPane); + expect(container.read(codePaneVisibleStateProvider).runtimeType, bool); + + // Update the widget tree to dispose the provider + await tester.pumpWidget(const MaterialApp()); + + // Verify that the provider was disposed + expect(() => container.read(codePaneVisibleStateProvider), + throwsA(isA())); + expect( + () => container.read(codePaneVisibleStateProvider), + throwsA( + isA().having( + (e) => e.message, + 'message', + contains('was already disposed'), + ), + ), + ); + }); }); } From 83c6e428644abd0c4624d999c7267b7ba24b8265 Mon Sep 17 00:00:00 2001 From: Yashas H Majmudar Date: Thu, 28 Mar 2024 14:25:26 +0530 Subject: [PATCH 087/138] fix: cleanup code and logic fixup --- lib/app.dart | 2 +- lib/providers/collection_providers.dart | 19 +++++++++---------- lib/providers/ui_providers.dart | 2 ++ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index caae2729..f6bc7c51 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -57,7 +57,7 @@ class _AppState extends ConsumerState with WindowListener { bool isPreventClose = await windowManager.isPreventClose(); if (isPreventClose) { if (ref.watch( - settingsProvider.select((value) => value.promptBeforeClosing)) && ref.watch(collectionStateNotifierProvider.notifier).changed) { + settingsProvider.select((value) => value.promptBeforeClosing)) && ref.watch(changeMadeProvider)) { showDialog( context: context, builder: (_) => AlertDialog( diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 6c3f1411..ae76450a 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -47,7 +47,6 @@ class CollectionStateNotifier final Ref ref; final HiveHandler hiveHandler; final baseResponseModel = const ResponseModel(); - bool changed = false; bool hasId(String id) => state?.keys.contains(id) ?? false; @@ -63,7 +62,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newRequestModel; state = map; - changed = true; + ref.read(changeMadeProvider.notifier).update((_) => true); ref .read(requestSequenceProvider.notifier) .update((state) => [id, ...state]); @@ -75,7 +74,7 @@ class CollectionStateNotifier final itemId = itemIds.removeAt(oldIdx); itemIds.insert(newIdx, itemId); ref.read(requestSequenceProvider.notifier).state = [...itemIds]; - changed = true; + ref.read(changeMadeProvider.notifier).update((_) => true); } void remove(String id) { @@ -98,7 +97,7 @@ class CollectionStateNotifier var map = {...state!}; map.remove(id); state = map; - changed = true; + ref.read(changeMadeProvider.notifier).update((_) => true); } void clearResponse(String? id) { @@ -112,7 +111,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newModel; state = map; - changed = true; + ref.read(changeMadeProvider.notifier).update((_) => true); } void duplicate(String id) { @@ -129,7 +128,7 @@ class CollectionStateNotifier var map = {...state!}; map[newId] = newModel; state = map; - changed = true; + ref.read(changeMadeProvider.notifier).update((_) => true); ref.read(requestSequenceProvider.notifier).state = [...itemIds]; ref.read(selectedIdStateProvider.notifier).state = newId; @@ -174,7 +173,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newModel; state = map; - changed = true; + ref.read(changeMadeProvider.notifier).update((_) => true); } Future sendRequest(String id) async { @@ -191,7 +190,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = requestModel.copyWith(isWorking: true); state = map; - changed = true; + ref.read(changeMadeProvider.notifier).update((_) => true); (http.Response?, Duration?, String?)? responseRec = await request( requestModel, @@ -222,7 +221,7 @@ class CollectionStateNotifier map = {...state!}; map[id] = newRequestModel; state = map; - changed = true; + ref.read(changeMadeProvider.notifier).update((_) => true); } Future clearData() async { @@ -232,7 +231,7 @@ class CollectionStateNotifier ref.read(clearDataStateProvider.notifier).state = false; ref.read(requestSequenceProvider.notifier).state = []; state = {}; - changed = true; + ref.read(changeMadeProvider.notifier).update((_) => false); } bool loadData() { diff --git a/lib/providers/ui_providers.dart b/lib/providers/ui_providers.dart index 62f83f70..22e2b611 100644 --- a/lib/providers/ui_providers.dart +++ b/lib/providers/ui_providers.dart @@ -6,6 +6,8 @@ final selectedIdEditStateProvider = StateProvider((ref) => null); final codePaneVisibleStateProvider = StateProvider((ref) => false); final saveDataStateProvider = StateProvider((ref) => false); final clearDataStateProvider = StateProvider((ref) => false); +final changeMadeProvider = StateProvider((ref) => false); + // final nameTextFieldControllerProvider = // StateProvider.autoDispose((ref) { // TextEditingController controller = TextEditingController(text: ""); From 34f9d27567a1f63c9cb75b7605b4558b5daa8698 Mon Sep 17 00:00:00 2001 From: Yashas H Majmudar Date: Thu, 28 Mar 2024 17:09:08 +0530 Subject: [PATCH 088/138] fix: renamed changeMade -> hasUnsavedChanges --- lib/app.dart | 2 +- lib/providers/collection_providers.dart | 18 +++++++++--------- lib/providers/ui_providers.dart | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index f6bc7c51..70e95213 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -57,7 +57,7 @@ class _AppState extends ConsumerState with WindowListener { bool isPreventClose = await windowManager.isPreventClose(); if (isPreventClose) { if (ref.watch( - settingsProvider.select((value) => value.promptBeforeClosing)) && ref.watch(changeMadeProvider)) { + settingsProvider.select((value) => value.promptBeforeClosing)) && ref.watch(hasUnsavedChangesProvider)) { showDialog( context: context, builder: (_) => AlertDialog( diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index ae76450a..4a5f5d56 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -62,7 +62,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newRequestModel; state = map; - ref.read(changeMadeProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); ref .read(requestSequenceProvider.notifier) .update((state) => [id, ...state]); @@ -74,7 +74,7 @@ class CollectionStateNotifier final itemId = itemIds.removeAt(oldIdx); itemIds.insert(newIdx, itemId); ref.read(requestSequenceProvider.notifier).state = [...itemIds]; - ref.read(changeMadeProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); } void remove(String id) { @@ -97,7 +97,7 @@ class CollectionStateNotifier var map = {...state!}; map.remove(id); state = map; - ref.read(changeMadeProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); } void clearResponse(String? id) { @@ -111,7 +111,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newModel; state = map; - ref.read(changeMadeProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); } void duplicate(String id) { @@ -128,7 +128,7 @@ class CollectionStateNotifier var map = {...state!}; map[newId] = newModel; state = map; - ref.read(changeMadeProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); ref.read(requestSequenceProvider.notifier).state = [...itemIds]; ref.read(selectedIdStateProvider.notifier).state = newId; @@ -173,7 +173,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newModel; state = map; - ref.read(changeMadeProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); } Future sendRequest(String id) async { @@ -190,7 +190,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = requestModel.copyWith(isWorking: true); state = map; - ref.read(changeMadeProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); (http.Response?, Duration?, String?)? responseRec = await request( requestModel, @@ -221,7 +221,7 @@ class CollectionStateNotifier map = {...state!}; map[id] = newRequestModel; state = map; - ref.read(changeMadeProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); } Future clearData() async { @@ -231,7 +231,7 @@ class CollectionStateNotifier ref.read(clearDataStateProvider.notifier).state = false; ref.read(requestSequenceProvider.notifier).state = []; state = {}; - ref.read(changeMadeProvider.notifier).update((_) => false); + ref.read(hasUnsavedChangesProvider.notifier).update((_) => false); } bool loadData() { diff --git a/lib/providers/ui_providers.dart b/lib/providers/ui_providers.dart index 22e2b611..e4b10677 100644 --- a/lib/providers/ui_providers.dart +++ b/lib/providers/ui_providers.dart @@ -6,7 +6,7 @@ final selectedIdEditStateProvider = StateProvider((ref) => null); final codePaneVisibleStateProvider = StateProvider((ref) => false); final saveDataStateProvider = StateProvider((ref) => false); final clearDataStateProvider = StateProvider((ref) => false); -final changeMadeProvider = StateProvider((ref) => false); +final hasUnsavedChangesProvider = StateProvider((ref) => false); // final nameTextFieldControllerProvider = // StateProvider.autoDispose((ref) { From 20cf67a594aa8f25468c2e187208cd3625834471 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Thu, 28 Mar 2024 21:11:22 +0530 Subject: [PATCH 089/138] fixes --- lib/consts.dart | 2 +- lib/widgets/video_previewer.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/consts.dart b/lib/consts.dart index d188e4a2..00130897 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -387,7 +387,7 @@ const Map>> kSubTypeDefaultViewOptions: kPreviewBodyViewOptions, }, kTypeVideo: { - kSubTypeDefaultViewOptions: kNoBodyViewOptions, + kSubTypeDefaultViewOptions: kPreviewBodyViewOptions, }, kTypeText: { kSubTypeDefaultViewOptions: kRawBodyViewOptions, diff --git a/lib/widgets/video_previewer.dart b/lib/widgets/video_previewer.dart index a6461b5e..c077e569 100644 --- a/lib/widgets/video_previewer.dart +++ b/lib/widgets/video_previewer.dart @@ -43,7 +43,7 @@ class _VideoPreviewerState extends State { void _initializeVideoPlayer() async { final tempDir = await getTemporaryDirectory(); _tempVideoFile = File( - '${tempDir.path}/temp_video_${DateTime.now().millisecondsSinceEpoch}.mp4'); + '${tempDir.path}/temp_video_${DateTime.now().millisecondsSinceEpoch}'); try { await _tempVideoFile?.writeAsBytes(widget.videoBytes); _videoController = VideoPlayerController.file(_tempVideoFile!) From 4a92a621ad3c01a679e58c07df81d02e6bb6c8b7 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Thu, 28 Mar 2024 21:23:56 +0530 Subject: [PATCH 090/138] Update README.md --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f6f73d62..3297c14e 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,16 @@ Here is the complete list of mimetypes that can be directly previewed in API Das | File Type | Mimetype | Extension | Comment | | --------- | -------------------------- | ----------------- | -------- | | PDF | `application/pdf` | `.pdf` | | -| CSV | `text/csv` | `.csv` | Can be improved | +| Video | `video/mp4` | `.mp4` | | +| Video | `video/webm` | `.webm` | | +| Video | `video/x-ms-wmv` | `.wmv` | | +| Video | `video/x-ms-asf` | `.wmv` | | +| Video | `video/avi` | `.avi` | | +| Video | `video/msvideo` | `.avi` | | +| Video | `video/x-msvideo` | `.avi` | | +| Video | `video/quicktime` | `.mov` | | +| Video | `video/x-quicktime` | `.mov` | | +| Video | `video/x-matroska` | `.mkv` | | | Image | `image/apng` | `.apng` | Animated | | Image | `image/avif` | `.avif` | | | Image | `image/bmp` | `.bmp` | | @@ -188,6 +197,7 @@ Here is the complete list of mimetypes that can be directly previewed in API Das | Audio | `audio/x-m4a` | `.m4a` | | | Audio | `audio/wav` | `.wav` | | | Audio | `audio/wave` | `.wav` | | +| CSV | `text/csv` | `.csv` | Can be improved | We welcome PRs to add support for previewing other multimedia mimetypes. Please go ahead and raise an issue so that we can discuss the approach. We are adding support for other mimetypes with each release. But, if you are looking for any particular mimetype support, please go ahead and open an issue. We will prioritize it's addition. From 4932be5ba75e122237da444a2075a28729669e1d Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Thu, 28 Mar 2024 21:46:54 +0530 Subject: [PATCH 091/138] Update collection_providers.dart --- lib/providers/collection_providers.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 5068f4ce..8f00b039 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -181,8 +181,10 @@ class CollectionStateNotifier // set current model's isWorking to true and update state var map = {...state!}; - map[id] = - requestModel.copyWith(isWorking: true, sendingTime: DateTime.now()); + map[id] = requestModel.copyWith( + isWorking: true, + sendingTime: DateTime.now(), + ); state = map; (http.Response?, Duration?, String?)? responseRec = await request( From 6c8686de0affb7f8b3fad5e11e6ef6d3c003135b Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Thu, 28 Mar 2024 22:02:25 +0530 Subject: [PATCH 092/138] Fix time elapsed sending widget --- lib/widgets/response_widgets.dart | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index 2d913f17..a3d9f20b 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -1,6 +1,4 @@ import 'dart:async'; - -import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:http_parser/http_parser.dart'; @@ -38,8 +36,10 @@ class NotSentWidget extends StatelessWidget { class SendingWidget extends StatefulWidget { final DateTime? startSendingTime; - final bool isTest; - const SendingWidget({super.key, required this.startSendingTime, this.isTest=false}); + const SendingWidget({ + super.key, + required this.startSendingTime, + }); @override State createState() => _SendingWidgetState(); @@ -53,8 +53,10 @@ class _SendingWidgetState extends State { void initState() { super.initState(); if (widget.startSendingTime != null) { - _millisecondsElapsed = widget.isTest ? 0 : - DateTime.now().difference(widget.startSendingTime!).inMilliseconds; + _millisecondsElapsed = + (DateTime.now().difference(widget.startSendingTime!).inMilliseconds ~/ + 100) * + 100; _timer = Timer.periodic(const Duration(milliseconds: 100), _updateTimer); } } @@ -85,7 +87,10 @@ class _SendingWidgetState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon(Icons.alarm), + Icon( + Icons.alarm, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), const SizedBox( width: 10, ), @@ -94,7 +99,9 @@ class _SendingWidgetState extends State { textAlign: TextAlign.center, overflow: TextOverflow.fade, softWrap: false, - style: kTextStyleButton, + style: kTextStyleButton.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), ), ], ), @@ -103,7 +110,6 @@ class _SendingWidgetState extends State { ], ); } - } class ResponsePaneHeader extends StatelessWidget { From 5c74a92296d38ad0f4559caf7507eeffbaa25364 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Thu, 28 Mar 2024 22:06:14 +0530 Subject: [PATCH 093/138] Update response_widgets_test.dart --- test/widgets/response_widgets_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/test/widgets/response_widgets_test.dart b/test/widgets/response_widgets_test.dart index 3bd5d2d6..c5617035 100644 --- a/test/widgets/response_widgets_test.dart +++ b/test/widgets/response_widgets_test.dart @@ -34,7 +34,6 @@ void main() { home: Scaffold( body: SendingWidget( startSendingTime: DateTime.now(), - isTest: true, ), ), ), From 4518d54af3ff0cbe87f1e60e8c088467b9113d1c Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Thu, 28 Mar 2024 23:35:45 +0530 Subject: [PATCH 094/138] Update collection_providers.dart --- lib/providers/collection_providers.dart | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 4a5f5d56..92b07124 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -62,11 +62,11 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newRequestModel; state = map; - ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); ref .read(requestSequenceProvider.notifier) .update((state) => [id, ...state]); ref.read(selectedIdStateProvider.notifier).state = newRequestModel.id; + ref.read(hasUnsavedChangesProvider.notifier).state = true; } void reorder(int oldIdx, int newIdx) { @@ -74,7 +74,7 @@ class CollectionStateNotifier final itemId = itemIds.removeAt(oldIdx); itemIds.insert(newIdx, itemId); ref.read(requestSequenceProvider.notifier).state = [...itemIds]; - ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).state = true; } void remove(String id) { @@ -97,7 +97,7 @@ class CollectionStateNotifier var map = {...state!}; map.remove(id); state = map; - ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).state = true; } void clearResponse(String? id) { @@ -111,7 +111,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newModel; state = map; - ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).state = true; } void duplicate(String id) { @@ -128,10 +128,10 @@ class CollectionStateNotifier var map = {...state!}; map[newId] = newModel; state = map; - ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); ref.read(requestSequenceProvider.notifier).state = [...itemIds]; ref.read(selectedIdStateProvider.notifier).state = newId; + ref.read(hasUnsavedChangesProvider.notifier).state = true; } void update( @@ -173,7 +173,7 @@ class CollectionStateNotifier var map = {...state!}; map[id] = newModel; state = map; - ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).state = true; } Future sendRequest(String id) async { @@ -190,7 +190,6 @@ class CollectionStateNotifier var map = {...state!}; map[id] = requestModel.copyWith(isWorking: true); state = map; - ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); (http.Response?, Duration?, String?)? responseRec = await request( requestModel, @@ -221,7 +220,7 @@ class CollectionStateNotifier map = {...state!}; map[id] = newRequestModel; state = map; - ref.read(hasUnsavedChangesProvider.notifier).update((_) => true); + ref.read(hasUnsavedChangesProvider.notifier).state = true; } Future clearData() async { @@ -231,7 +230,7 @@ class CollectionStateNotifier ref.read(clearDataStateProvider.notifier).state = false; ref.read(requestSequenceProvider.notifier).state = []; state = {}; - ref.read(hasUnsavedChangesProvider.notifier).update((_) => false); + ref.read(hasUnsavedChangesProvider.notifier).state = true; } bool loadData() { @@ -272,6 +271,7 @@ class CollectionStateNotifier } await hiveHandler.removeUnused(); ref.read(saveDataStateProvider.notifier).state = false; + ref.read(hasUnsavedChangesProvider.notifier).state = false; } Future> exportDataToHAR() async { From 5f09e19f8ccfd138cb82343906046de3b725c50d Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Thu, 28 Mar 2024 23:35:58 +0530 Subject: [PATCH 095/138] Update collection_pane.dart --- lib/screens/home_page/collection_pane.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index 0ede2021..934c5b66 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -15,6 +15,7 @@ class CollectionPane extends ConsumerWidget { final overlayWidget = OverlayWidgetTemplate(context: context); final collection = ref.watch(collectionStateNotifierProvider); final savingData = ref.watch(saveDataStateProvider); + final hasUnsavedChanges = ref.watch(hasUnsavedChangesProvider); if (collection == null) { return const Center( child: CircularProgressIndicator(), @@ -31,7 +32,7 @@ class CollectionPane extends ConsumerWidget { alignment: WrapAlignment.spaceBetween, children: [ TextButton.icon( - onPressed: savingData + onPressed: (savingData || !hasUnsavedChanges) ? null : () async { overlayWidget.show( From 049a31819e54216a8e9b2f7ca594985975662664 Mon Sep 17 00:00:00 2001 From: Sixtus Agbo Date: Fri, 29 Mar 2024 00:39:15 +0100 Subject: [PATCH 096/138] Add test url constant --- test/providers/ui_providers_test.dart | 14 ++++++-------- test/test_consts.dart | 4 +++- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/providers/ui_providers_test.dart b/test/providers/ui_providers_test.dart index 1c4fde90..94a326ef 100644 --- a/test/providers/ui_providers_test.dart +++ b/test/providers/ui_providers_test.dart @@ -19,6 +19,8 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; +import '../test_consts.dart'; + void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -389,8 +391,7 @@ void main() { of: find.byType(URLField), matching: find.byType(TextFormField), ); - const url = 'https://api.foss42.com/country/codes'; - await tester.enterText(field, url); + await tester.enterText(field, kTestUrl); await tester.pump(); // Tap on the "Send" button @@ -434,8 +435,7 @@ void main() { of: find.byType(URLField), matching: find.byType(TextFormField), ); - const url = 'https://api.foss42.com/country/codes'; - await tester.enterText(field, url); + await tester.enterText(field, kTestUrl); await tester.pump(); // Tap on the "Send" button @@ -483,8 +483,7 @@ void main() { of: find.byType(URLField), matching: find.byType(TextFormField), ); - const url = 'https://api.foss42.com/country/codes'; - await tester.enterText(field, url); + await tester.enterText(field, kTestUrl); await tester.pump(); // Tap on the "Send" button @@ -541,8 +540,7 @@ void main() { of: find.byType(URLField), matching: find.byType(TextFormField), ); - const url = 'https://api.foss42.com/country/codes'; - await tester.enterText(field, url); + await tester.enterText(field, kTestUrl); await tester.pump(); // Tap on the "Send" button diff --git a/test/test_consts.dart b/test/test_consts.dart index f0a9b779..08e2c7e3 100644 --- a/test/test_consts.dart +++ b/test/test_consts.dart @@ -1,5 +1,5 @@ -import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; final kThemeDataDark = ThemeData( useMaterial3: true, @@ -570,3 +570,5 @@ Uint8List kBodyBytesJpeg = Uint8List.fromList([ 255, 217 ]); + +const kTestUrl = 'https://api.apidash.dev/country/codes'; From 281dcaf06a23b7a737b4f7ff1cfd4958881e65ef Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Fri, 29 Mar 2024 19:13:28 +0530 Subject: [PATCH 097/138] Update http_service.dart --- lib/services/http_service.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 35a45e36..dec0b516 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -1,11 +1,10 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; - -import 'package:apidash/consts.dart'; -import 'package:apidash/models/models.dart'; -import 'package:apidash/utils/utils.dart'; import 'package:http/http.dart' as http; +import 'package:apidash/utils/utils.dart'; +import 'package:apidash/models/models.dart'; +import 'package:apidash/consts.dart'; Future<(http.Response?, Duration?, String?)> request( RequestModel requestModel, { From 7c3b3119f5c311a3d0304075a7743d2bf387a408 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Fri, 29 Mar 2024 19:22:07 +0530 Subject: [PATCH 098/138] Update test_consts.dart --- test/test_consts.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_consts.dart b/test/test_consts.dart index 08e2c7e3..6ef47887 100644 --- a/test/test_consts.dart +++ b/test/test_consts.dart @@ -13,6 +13,8 @@ final kThemeDataLight = ThemeData( brightness: Brightness.light, ); +const kTestUrl = 'https://api.apidash.dev'; + Uint8List kBodyBytesJpeg = Uint8List.fromList([ 255, 216, @@ -570,5 +572,3 @@ Uint8List kBodyBytesJpeg = Uint8List.fromList([ 255, 217 ]); - -const kTestUrl = 'https://api.apidash.dev/country/codes'; From d601094ef46d2e97d8b66814d3b1286c8b0bfec6 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:03:28 +0530 Subject: [PATCH 099/138] added boundary in julia codegen --- lib/codegen/codegen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index 43f3b346..d792639f 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -65,7 +65,7 @@ class Codegen { case CodegenLanguage.javaOkHttp: return JavaOkHttpCodeGen().getCode(rM); case CodegenLanguage.juliaHttp: - return JuliaHttpClientCodeGen().getCode(rM); + return JuliaHttpClientCodeGen().getCode(rM, boundary: boundary); case CodegenLanguage.kotlinOkHttp: return KotlinOkHttpCodeGen().getCode(rM); case CodegenLanguage.pythonHttpClient: From 4d073ec9c17d9432b23ece1e03e63a97207a7fbb Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:05:14 +0530 Subject: [PATCH 100/138] added templates for package import, url and boundary --- lib/codegen/julia/http.dart | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index b1d1e96b..0fd60669 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -7,10 +7,18 @@ import 'package:apidash/utils/utils.dart' import 'package:apidash/models/models.dart' show RequestModel; class JuliaHttpClientCodeGen { - final String kTemplateStart = """using HTTP,JSON + final String kTemplateStart = """ +using HTTP{% if hasJson %}, JSON{% endif %} +\n +"""; + final String kTemplateUrl = """ url = "{{url}}" - +\n +"""; + final String kTemplateBoundary = """ +boundary = "{{boundary}}" +\n """; String kTemplateParams = """ From 6deaaf2169ebe139a659bf640e4f46719376f141 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:05:36 +0530 Subject: [PATCH 101/138] added param dict template --- lib/codegen/julia/http.dart | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index 0fd60669..0ee167b6 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -22,23 +22,12 @@ boundary = "{{boundary}}" """; String kTemplateParams = """ -{% set new_params = params | replace(":", "=>") | replace("{", "(") | replace("}", ")") %} - -params = Dict{{new_params}} -"""; - - int kParamsPadding = 9; - - String kTemplateBody = ''' -{% set new_params = body | replace(":", "=>") | replace("{", "(") | replace("}", ")") %} - -payload = Dict{{new_params}} -'''; - - String kTemplateJson = """ -{% set new_params = body | replace(":", "=>") | replace("{", "(") | replace("}", ")") %} - -payload = Dict{{new_params}} +params = Dict( +{%- for name, value in params %} + "{{ name }}" => "{{ value }}", +{%- endfor %} +) +\n """; String kTemplateHeaders = """ From bbbf686f804bfc67b692d2752b4612a7cc45513d Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:05:51 +0530 Subject: [PATCH 102/138] added header dict template --- lib/codegen/julia/http.dart | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index 0ee167b6..44fba04d 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -31,15 +31,14 @@ params = Dict( """; String kTemplateHeaders = """ -{% set new_params = headers | replace(":", "=>") | replace("{", "(") | replace("}", ")") %} - -headers = Dict{{new_params}} +headers = Dict( +{%- for name, value in headers %} + "{{ name }}" => "{{ value }}", +{%- endfor %} +) +\n """; - String kTemplateFormHeaderContentType = ''' -multipart/form-data; boundary={{boundary}}'''; - - int kHeadersPadding = 10; String kTemplateRequest = """ From 31469e3651cce1cb9b60e8ac578a962145561ab2 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:06:18 +0530 Subject: [PATCH 103/138] added formdata and text/json payload template --- lib/codegen/julia/http.dart | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index 44fba04d..7f63985a 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -39,6 +39,27 @@ headers = Dict( \n """; + final String kTemplateFormDataBody = ''' +{{ 'data' if hasFile else 'payload' }} = Dict( +{%- for data in formdata %} +{%- if data.type == "text" %} + "{{ data.name }}" => "{{ data.value }}", +{%- else %} + "{{ data.name }}" => open("{{ data.value }}"), +{%- endif %} +{%- endfor %} +) +{%- if hasFile %} + +payload = HTTP.Form(data{% if boundary is defined %}, boundary=boundary{% endif %}) +{%- endif %} +\n +'''; + + String kTemplateBody = """ +payload = \"\"\"{{ body }}\"\"\" +\n +"""; String kTemplateRequest = """ From 361846997a456b5adb85eb56d3a3c5d57ce26013 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:07:13 +0530 Subject: [PATCH 104/138] removed multipart form builder in favor of native HTTP.Form --- lib/codegen/julia/http.dart | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index 7f63985a..be0fb8a0 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -62,41 +62,9 @@ payload = \"\"\"{{ body }}\"\"\" """; String kTemplateRequest = """ - - -response = HTTP.{{method}}(url +response = HTTP.request("{{ method | upper }}", url """; - final String kStringFormDataBody = r''' -function build_data_list(fields) - dataList = [] - for field in fields - name = field["name"] - value = field["value"] - type_ = get(field, "type", "text") - - push!(dataList, b"--{{boundary}}") - if type_ == "text" - push!(dataList, b"Content-Disposition: form-data; name=\"$name\"") - push!(dataList, b"Content-Type: text/plain") - push!(dataList, b"") - push!(dataList, codeunits(value)) - elseif type_ == "file" - push!(dataList, b"Content-Disposition: form-data; name=\"$name\"; filename=\"$value\"") - push!(dataList, b"Content-Type: $value") - push!(dataList, b"") - push!(dataList, String(read(value))) - end - end - push!(dataList, "--{{boundary}}--") - push!(dataList, b"") - return dataList -end - -dataList = build_data_list({{fields_list}}) -payload = join(dataList, b"\r\n") -'''; - String kStringRequestParams = """, query=params"""; String kStringRequestBody = """, payload=payload"""; From 93fdb71ca43138f1950095f1e3df57aa84118a5a Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:07:53 +0530 Subject: [PATCH 105/138] fixed request template --- lib/codegen/julia/http.dart | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index be0fb8a0..bf44ee55 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -67,17 +67,15 @@ response = HTTP.request("{{ method | upper }}", url String kStringRequestParams = """, query=params"""; - String kStringRequestBody = """, payload=payload"""; - - String kStringRequestJson = """, JSON.json(payload)"""; + String kStringRequestBody = """, body=payload"""; String kStringRequestHeaders = """, headers=headers"""; - final String kStringRequestEnd = """ -) + final String kStringRequestEnd = r""" +, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; String? getCode(RequestModel requestModel) { From 21015ed39d8970bea1d51d133619fb32e9390944 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:08:11 +0530 Subject: [PATCH 106/138] added optional boundary as argument --- lib/codegen/julia/http.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index bf44ee55..517039f2 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -78,7 +78,7 @@ println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response. println("Response Body: \n\n$(String(response.body))") """; - String? getCode(RequestModel requestModel) { + String? getCode(RequestModel requestModel, {String? boundary}) { try { String result = ""; bool hasQuery = false; From 33cea56a52442113c38680588c691539b22c9754 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:08:45 +0530 Subject: [PATCH 107/138] added boundary and url params builder --- lib/codegen/julia/http.dart | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index 517039f2..d2e4c6a6 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -93,19 +93,27 @@ println("Response Body: \n\n$(String(response.body))") ); Uri? uri = rec.$1; if (uri != null) { - var templateStartUrl = jj.Template(kTemplateStart); - result += templateStartUrl.render({ - "url": stripUriParams(uri), + final templateStart = jj.Template(kTemplateStart); + result += templateStart.render({ + // "hasJson": requestModel.hasBody && requestModel.hasJsonContentType && requestModel.hasJsonData, + "hasJson": false, // we manually send false because we do not require JSON package }); + final templateUrl = jj.Template(kTemplateUrl); + result += templateUrl.render({"url": stripUriParams(uri)}); + + if (requestModel.hasFormData && requestModel.hasFileInFormData) { + boundary ??= getNewUuid(); + final templateParams = jj.Template(kTemplateBoundary); + result += templateParams.render({"boundary": boundary}); + } + if (uri.hasQuery) { var params = uri.queryParameters; if (params.isNotEmpty) { hasQuery = true; - var templateParams = jj.Template(kTemplateParams); - var paramsString = kEncoder.convert(params); - paramsString = padMultilineString(paramsString, kParamsPadding); - result += templateParams.render({"params": paramsString}); + final templateParams = jj.Template(kTemplateParams); + result += templateParams.render({"params": params}); } } From 24e670e098270f4b4c3d1613b60291a60609b26c Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:09:23 +0530 Subject: [PATCH 108/138] added formdata support --- lib/codegen/julia/http.dart | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index d2e4c6a6..e0d42a85 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -117,14 +117,23 @@ println("Response Body: \n\n$(String(response.body))") } } - if (requestModel.hasJsonData) { - hasJsonBody = true; - var templateBody = jj.Template(kTemplateJson); - result += templateBody.render({"body": requestModel.requestBody}); - } else if (requestModel.hasTextData) { + if (requestModel.hasJsonData || requestModel.hasTextData) { hasBody = true; - var templateBody = jj.Template(kTemplateBody); - result += templateBody.render({"body": requestModel.requestBody}); + final templateBody = jj.Template(kTemplateBody); + var bodyStr = requestModel.requestBody; + result += templateBody.render({"body": bodyStr}); + } + + if (requestModel.hasFormData) { + hasBody = true; + final formDataBodyData = jj.Template(kTemplateFormDataBody); + result += formDataBodyData.render( + { + "hasFile": requestModel.hasFileInFormData, + "formdata": requestModel.formDataMapList, + "boundary": boundary, + }, + ); } var headersList = requestModel.enabledRequestHeaders; From d24b2c21271964ab1a0a9f9ada5cb642b42fc6bd Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:10:02 +0530 Subject: [PATCH 109/138] added header support --- lib/codegen/julia/http.dart | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index e0d42a85..b1fa7d84 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -139,34 +139,26 @@ println("Response Body: \n\n$(String(response.body))") var headersList = requestModel.enabledRequestHeaders; if (headersList != null || hasBody) { var headers = requestModel.enabledHeadersMap; - if (requestModel.hasFormData) { - var formHeaderTemplate = - jj.Template(kTemplateFormHeaderContentType); - headers[HttpHeaders.contentTypeHeader] = formHeaderTemplate.render({ - "boundary": uuid, - }); + + if (!requestModel.hasContentTypeHeader) { + if (hasBody) { + headers[HttpHeaders.contentTypeHeader] = requestModel.requestBodyContentType.header; + } + + if (requestModel.hasFormData) { + headers[HttpHeaders.contentTypeHeader] = requestModel.hasFileInFormData + ? "multipart/form-data; boundary=\$(boundary)" + : "application/x-www-form-urlencoded"; + } } + if (headers.isNotEmpty || hasBody) { hasHeaders = true; - if (hasBody) { - headers[HttpHeaders.contentTypeHeader] = - requestModel.requestBodyContentType.header; - } - var headersString = kEncoder.convert(headers); - headersString = padMultilineString(headersString, kHeadersPadding); var templateHeaders = jj.Template(kTemplateHeaders); - result += templateHeaders.render({"headers": headersString}); + result += templateHeaders.render({"headers": headers}); } } - if (requestModel.hasFormData) { - var formDataBodyData = jj.Template(kStringFormDataBody); - result += formDataBodyData.render( - { - "fields_list": json.encode(requestModel.formDataMapList), - "boundary": uuid, - }, - ); - } + var templateRequest = jj.Template(kTemplateRequest); result += templateRequest.render({ "method": requestModel.method.name.toLowerCase(), From 0f4d97e20a6caeb56032984a981ea46d544ef50c Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:10:22 +0530 Subject: [PATCH 110/138] request dispatcher fixed --- lib/codegen/julia/http.dart | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index b1fa7d84..d0792242 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -161,27 +161,24 @@ println("Response Body: \n\n$(String(response.body))") var templateRequest = jj.Template(kTemplateRequest); result += templateRequest.render({ - "method": requestModel.method.name.toLowerCase(), + "method": requestModel.method.name, }); - if (hasQuery) { - result += kStringRequestParams; + if (hasHeaders || requestModel.hasFormData) { + result += kStringRequestHeaders; } if (hasBody || requestModel.hasFormData) { result += kStringRequestBody; } - if (hasJsonBody || requestModel.hasFormData) { - result += kStringRequestJson; - } - - if (hasHeaders || requestModel.hasFormData) { - result += kStringRequestHeaders; + if (hasQuery) { + result += kStringRequestParams; } result += kStringRequestEnd; } + return result; } catch (e) { return null; From dcd3b9f9eb20b0c0534fc312d8994d037d0080c3 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:10:39 +0530 Subject: [PATCH 111/138] fixed imports and removed unused variables --- lib/codegen/julia/http.dart | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index d0792242..04f14047 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -1,9 +1,6 @@ import 'dart:io'; -import 'dart:convert'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/consts.dart'; -import 'package:apidash/utils/utils.dart' - show getNewUuid, getValidRequestUri, padMultilineString, stripUriParams; +import 'package:apidash/utils/utils.dart' show getNewUuid, getValidRequestUri, stripUriParams; import 'package:apidash/models/models.dart' show RequestModel; class JuliaHttpClientCodeGen { @@ -84,8 +81,6 @@ println("Response Body: \n\n$(String(response.body))") bool hasQuery = false; bool hasHeaders = false; bool hasBody = false; - bool hasJsonBody = false; - String uuid = getNewUuid(); var rec = getValidRequestUri( requestModel.url, From 329fc8d8079c09ed3fd8a3776ae32012968c3f4a Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:11:03 +0530 Subject: [PATCH 112/138] fixed all existing tests and added tests for POST 4 to POST 9 --- test/codegen/julia_http_codegen_test.dart | 562 +++++++++++++--------- 1 file changed, 335 insertions(+), 227 deletions(-) diff --git a/test/codegen/julia_http_codegen_test.dart b/test/codegen/julia_http_codegen_test.dart index 2b5161eb..68638d3f 100644 --- a/test/codegen/julia_http_codegen_test.dart +++ b/test/codegen/julia_http_codegen_test.dart @@ -8,446 +8,554 @@ void main() { group('GET Request', () { test('GET 1', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.apidash.dev" +response = HTTP.request("GET", url, status_exception=false) -response = HTTP.get(url) - -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet1, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet1, "https"), expectedCode); }); test('GET 2', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.apidash.dev/country/data" - params = Dict( - "code"=> "US" - ) + "code" => "US", +) -response = HTTP.get(url, query=params) +response = HTTP.request("GET", url, query=params, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet2, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet2, "https"), expectedCode); }); test('GET 3', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.apidash.dev/country/data" - params = Dict( - "code"=> "IND" - ) + "code" => "IND", +) -response = HTTP.get(url, query=params) +response = HTTP.request("GET", url, query=params, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet3, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet3, "https"), expectedCode); }); test('GET 4', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.apidash.dev/humanize/social" - params = Dict( - "num"=> "8700000", - "digits"=> "3", - "system"=> "SS", - "add_space"=> "true", - "trailing_zeros"=> "true" - ) + "num" => "8700000", + "digits" => "3", + "system" => "SS", + "add_space" => "true", + "trailing_zeros" => "true", +) -response = HTTP.get(url, query=params) +response = HTTP.request("GET", url, query=params, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet4, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet4, "https"), expectedCode); }); test('GET 5', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.github.com/repos/foss42/apidash" - headers = Dict( - "User-Agent"=> "Test Agent" - ) + "User-Agent" => "Test Agent", +) -response = HTTP.get(url, headers=headers) +response = HTTP.request("GET", url, headers=headers, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet5, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet5, "https"), expectedCode); }); test('GET 6', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.github.com/repos/foss42/apidash" - params = Dict( - "raw"=> "true" - ) + "raw" => "true", +) headers = Dict( - "User-Agent"=> "Test Agent" - ) + "User-Agent" => "Test Agent", +) -response = HTTP.get(url, query=params, headers=headers) +response = HTTP.request("GET", url, headers=headers, query=params, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet6, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet6, "https"), expectedCode); }); test('GET 7', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.apidash.dev" +response = HTTP.request("GET", url, status_exception=false) -response = HTTP.get(url) - -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet7, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet7, "https"), expectedCode); }); test('GET 8', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.github.com/repos/foss42/apidash" - params = Dict( - "raw"=> "true" - ) + "raw" => "true", +) headers = Dict( - "User-Agent"=> "Test Agent" - ) + "User-Agent" => "Test Agent", +) -response = HTTP.get(url, query=params, headers=headers) +response = HTTP.request("GET", url, headers=headers, query=params, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet8, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet8, "https"), expectedCode); }); test('GET 9', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.apidash.dev/humanize/social" - params = Dict( - "num"=> "8700000", - "add_space"=> "true" - ) + "num" => "8700000", + "add_space" => "true", +) -response = HTTP.get(url, query=params) +response = HTTP.request("GET", url, query=params, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet9, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet9, "https"), expectedCode); }); test('GET 10', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.apidash.dev/humanize/social" - headers = Dict( - "User-Agent"=> "Test Agent" - ) + "User-Agent" => "Test Agent", +) -response = HTTP.get(url, headers=headers) +response = HTTP.request("GET", url, headers=headers, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode( - CodegenLanguage.juliaHttp, requestModelGet10, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet10, "https"), expectedCode); }); test('GET 11', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.apidash.dev/humanize/social" - params = Dict( - "num"=> "8700000", - "digits"=> "3" - ) + "num" => "8700000", + "digits" => "3", +) headers = Dict( - "User-Agent"=> "Test Agent" - ) + "User-Agent" => "Test Agent", +) -response = HTTP.get(url, query=params, headers=headers) +response = HTTP.request("GET", url, headers=headers, query=params, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode( - CodegenLanguage.juliaHttp, requestModelGet11, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet11, "https"), expectedCode); }); test('GET 12', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.apidash.dev/humanize/social" +response = HTTP.request("GET", url, status_exception=false) -response = HTTP.get(url) - -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode( - CodegenLanguage.juliaHttp, requestModelGet12, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet12, "https"), expectedCode); }); }); group('HEAD Request', () { test('HEAD 1', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://api.apidash.dev" +response = HTTP.request("HEAD", url, status_exception=false) -response = HTTP.head(url) - -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode( - CodegenLanguage.juliaHttp, requestModelHead1, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelHead1, "https"), expectedCode); }); test('HEAD 2', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP -url = "https://api.apidash.dev" +url = "http://api.apidash.dev" +response = HTTP.request("HEAD", url, status_exception=false) -response = HTTP.head(url) - -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode( - CodegenLanguage.juliaHttp, requestModelHead2, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelHead2, "http"), expectedCode); }); }); group('POST Request', () { test('POST 1', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = """using HTTP url = "https://api.apidash.dev/case/lower" - -payload = Dict( -"text"=> "I LOVE Flutter" -) +payload = \"\"\"{ +"text": "I LOVE Flutter" +}\"\"\" headers = Dict( - "content-type"=> "text/plain" - ) + "content-type" => "text/plain", +) -response = HTTP.post(url, payload=payload, headers=headers) +response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \\n\\n\$(String(response.body))") """; - expect( - codeGen.getCode( - CodegenLanguage.juliaHttp, requestModelPost1, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost1, "https"), expectedCode); }); test('POST 2', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = """using HTTP url = "https://api.apidash.dev/case/lower" +payload = \"\"\"{ +"text": "I LOVE Flutter", +"flag": null, +"male": true, +"female": false, +"no": 1.2, +"arr": ["null", "true", "false", null] +}\"\"\" -payload = Dict( -"text"=> "I LOVE Flutter", -"flag"=> null, -"male"=> true, -"female"=> false, -"no"=> 1.2, -"arr"=> ["null", "true", "false", null] +headers = Dict( + "content-type" => "application/json", ) -response = HTTP.post(url, JSON.json(payload)) +response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \\n\\n\$(String(response.body))") """; - expect( - codeGen.getCode( - CodegenLanguage.juliaHttp, requestModelPost2, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost2, "https"), expectedCode); }); test('POST 3', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = """using HTTP url = "https://api.apidash.dev/case/lower" +payload = \"\"\"{ +"text": "I LOVE Flutter" +}\"\"\" + +headers = Dict( + "User-Agent" => "Test Agent", + "content-type" => "application/json", +) + +response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) + +println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \\n\\n\$(String(response.body))") +"""; + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost3, "https"), expectedCode); + }); + + test('POST 4', () { + const expectedCode = r"""using HTTP + +url = "https://api.apidash.dev/io/form" payload = Dict( -"text"=> "I LOVE Flutter" + "text" => "API", + "sep" => "|", + "times" => "3", ) headers = Dict( - "User-Agent"=> "Test Agent" - ) + "content-type" => "application/x-www-form-urlencoded", +) -response = HTTP.post(url, JSON.json(payload), headers=headers) +response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") +"""; + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost4, "https"), expectedCode); + }); + + test('POST 5', () { + const expectedCode = r"""using HTTP + +url = "https://api.apidash.dev/io/form" + +payload = Dict( + "text" => "API", + "sep" => "|", + "times" => "3", +) + +headers = Dict( + "User-Agent" => "Test Agent", + "content-type" => "application/x-www-form-urlencoded", +) + +response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) + +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") +"""; + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost5, "https"), expectedCode); + }); + test('POST 6', () { + const expectedCode = r"""using HTTP + +url = "https://api.apidash.dev/io/img" + +boundary = "467fbea0-c2dc-1f41-b12d-9d9923a5f7b8" + +data = Dict( + "token" => "xyz", + "imfile" => open("/Documents/up/1.png"), +) + +payload = HTTP.Form(data, boundary=boundary) + +headers = Dict( + "content-type" => "multipart/form-data; boundary=$(boundary)", +) + +response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) + +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; expect( - codeGen.getCode( - CodegenLanguage.juliaHttp, requestModelPost3, "https"), + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost6, "https", + boundary: "467fbea0-c2dc-1f41-b12d-9d9923a5f7b8"), + expectedCode); + }); + test('POST 7', () { + const expectedCode = r"""using HTTP + +url = "https://api.apidash.dev/io/img" + +boundary = "9440cbe0-c433-1f41-b12d-9d9923a5f7b8" + +data = Dict( + "token" => "xyz", + "imfile" => open("/Documents/up/1.png"), +) + +payload = HTTP.Form(data, boundary=boundary) + +headers = Dict( + "content-type" => "multipart/form-data; boundary=$(boundary)", +) + +response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) + +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") +"""; + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost7, "https", + boundary: "9440cbe0-c433-1f41-b12d-9d9923a5f7b8"), + expectedCode); + }); + test('POST 8', () { + const expectedCode = r"""using HTTP + +url = "https://api.apidash.dev/io/form" + +params = Dict( + "size" => "2", + "len" => "3", +) + +payload = Dict( + "text" => "API", + "sep" => "|", + "times" => "3", +) + +headers = Dict( + "content-type" => "application/x-www-form-urlencoded", +) + +response = HTTP.request("POST", url, headers=headers, body=payload, query=params, status_exception=false) + +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") +"""; + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost8, "https"), expectedCode); + }); + test('POST 9', () { + const expectedCode = r"""using HTTP + +url = "https://api.apidash.dev/io/img" + +boundary = "69573b00-c67f-1f41-b12d-9d9923a5f7b8" + +params = Dict( + "size" => "2", + "len" => "3", +) + +data = Dict( + "token" => "xyz", + "imfile" => open("/Documents/up/1.png"), +) + +payload = HTTP.Form(data, boundary=boundary) + +headers = Dict( + "User-Agent" => "Test Agent", + "Keep-Alive" => "true", + "content-type" => "multipart/form-data; boundary=$(boundary)", +) + +response = HTTP.request("POST", url, headers=headers, body=payload, query=params, status_exception=false) + +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") +"""; + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost9, "https", + boundary: "69573b00-c67f-1f41-b12d-9d9923a5f7b8"), expectedCode); }); }); group('PUT Request', () { test('PUT 1', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = """using HTTP url = "https://reqres.in/api/users/2" +payload = \"\"\"{ +"name": "morpheus", +"job": "zion resident" +}\"\"\" -payload = Dict( -"name"=> "morpheus", -"job"=> "zion resident" +headers = Dict( + "content-type" => "application/json", ) -response = HTTP.put(url, JSON.json(payload)) +response = HTTP.request("PUT", url, headers=headers, body=payload, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \\n\\n\$(String(response.body))") """; - expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPut1, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPut1, "https"), expectedCode); }); }); group('PATCH Request', () { test('PATCH 1', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = """using HTTP url = "https://reqres.in/api/users/2" +payload = \"\"\"{ +"name": "marfeus", +"job": "accountant" +}\"\"\" -payload = Dict( -"name"=> "marfeus", -"job"=> "accountant" +headers = Dict( + "content-type" => "application/json", ) -response = HTTP.patch(url, JSON.json(payload)) +response = HTTP.request("PATCH", url, headers=headers, body=payload, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \\n\\n\$(String(response.body))") """; - expect( - codeGen.getCode( - CodegenLanguage.juliaHttp, requestModelPatch1, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPatch1, "https"), expectedCode); }); }); group('DELETE Request', () { test('DELETE 1', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = r"""using HTTP url = "https://reqres.in/api/users/2" +response = HTTP.request("DELETE", url, status_exception=false) -response = HTTP.delete(url) - -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n\n$(String(response.body))") """; - expect( - codeGen.getCode( - CodegenLanguage.juliaHttp, requestModelDelete1, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelDelete1, "https"), expectedCode); }); test('DELETE 2', () { - const expectedCode = r"""using HTTP,JSON + const expectedCode = """using HTTP url = "https://reqres.in/api/users/2" +payload = \"\"\"{ +"name": "marfeus", +"job": "accountant" +}\"\"\" -payload = Dict( -"name"=> "marfeus", -"job"=> "accountant" +headers = Dict( + "content-type" => "application/json", ) -response = HTTP.delete(url, JSON.json(payload)) +response = HTTP.request("DELETE", url, headers=headers, body=payload, status_exception=false) -println("Status Code:", response.status) -println("Response Body:", String(response.body)) +println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \\n\\n\$(String(response.body))") """; - expect( - codeGen.getCode( - CodegenLanguage.juliaHttp, requestModelDelete2, "https"), - expectedCode); + expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelDelete2, "https"), expectedCode); }); }); } From 62fc4a020bacc5d7717bb79cc82b0ab03188a853 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sat, 30 Mar 2024 20:35:54 +0530 Subject: [PATCH 113/138] removed ruby files --- lib/codegen/codegen.dart | 4 - lib/codegen/ruby/faraday.dart | 184 ----- lib/consts.dart | 1 - test/codegen/ruby_faraday_codegen_test.dart | 744 -------------------- 4 files changed, 933 deletions(-) delete mode 100644 lib/codegen/ruby/faraday.dart delete mode 100644 test/codegen/ruby_faraday_codegen_test.dart diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index d792639f..76ea70c0 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -8,7 +8,6 @@ import 'kotlin/okhttp.dart'; import 'php/guzzle.dart'; import 'python/http_client.dart'; import 'python/requests.dart'; -import 'ruby/faraday.dart'; import 'rust/actix.dart'; import 'rust/curl_rust.dart'; import 'rust/reqwest.dart'; @@ -73,9 +72,6 @@ class Codegen { .getCode(rM, boundary: boundary ?? getNewUuid()); case CodegenLanguage.pythonRequests: return PythonRequestsCodeGen().getCode(rM, boundary: boundary); - case CodegenLanguage.rubyFaraday: - return RubyFaradayCodeGen() - .getCode(rM, boundary: boundary ?? getNewUuid()); case CodegenLanguage.rustActix: return RustActixCodeGen().getCode(rM, boundary: boundary); case CodegenLanguage.rustCurl: diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart deleted file mode 100644 index 8357ee03..00000000 --- a/lib/codegen/ruby/faraday.dart +++ /dev/null @@ -1,184 +0,0 @@ -import 'package:apidash/consts.dart'; -import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' show getValidRequestUri; -import 'package:apidash/utils/http_utils.dart' show stripUriParams; - -import 'package:apidash/models/models.dart' show RequestModel; - -// Note that delete is a special case in Faraday as API Dash supports request -// body inside delete reqest, but Faraday does not. Hence we need to manually -// setup request body for delete request and add that to request. -// -// Refer https://lostisland.github.io/faraday/#/getting-started/quick-start?id=get-head-delete-trace -class RubyFaradayCodeGen { - - final String kStringFaradayRequireStatement = """ -require 'uri' -require 'faraday' -"""; - - final String kStringFaradayMultipartRequireStatement = ''' -require 'faraday/multipart' -'''; - - final String kTemplateRequestUrl = """ -\nREQUEST_URL = URI("{{ url }}")\n\n -"""; - - final String kTemplateBody = """ -PAYLOAD = <<-{{ boundary }} -{{ body }} -{{ boundary }}\n\n -"""; - - final String kTemplateFormParamsWithFile = """ -PAYLOAD = { -{% for param in params %}{% if param.type == "text" %} "{{ param.name }}" => Faraday::Multipart::ParamPart.new("{{ param.value }}", "text/plain"), -{% elif param.type == "file" %} "{{ param.name }}" => Faraday::Multipart::FilePart.new("{{ param.value }}", "application/octet-stream"),{% endif %}{% endfor %} -}\n\n -"""; - - final String kTemplateFormParamsWithoutFile = """ -PAYLOAD = URI.encode_www_form({\n{% for param in params %} "{{ param.name }}" => "{{ param.value }}",\n{% endfor %}})\n\n -"""; - - final String kTemplateConnection = """ -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter{% if hasFile %}\n faraday.request :multipart{% endif %} -end\n\n -"""; - - final String kTemplateRequestStart = """ -response = conn.{{ method|lower }}(REQUEST_URL{% if doesMethodAcceptBody and containsBody %}, PAYLOAD{% endif %}) do |req|\n -"""; - - final String kTemplateRequestOptionsBoundary = """ - req.options.boundary = "{{ boundary }}"\n -"""; - - final String kTemplateRequestParams = """ - req.params = {\n{% for key, val in params %} "{{ key }}" => "{{ val }}",\n{% endfor %} }\n -"""; - - final String kTemplateRequestHeaders = """ - req.headers = {\n{% for key, val in headers %} "{{ key }}" => "{{ val }}",\n{% endfor %} }\n -"""; - - final String kStringDeleteRequestBody = """ - req.body = PAYLOAD -"""; - - final String kStringRequestEnd = """ -end\n -"""; - - final String kStringResponse = """ -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - - String? getCode( - RequestModel requestModel, { - String? boundary, - }) { - try { - String result = ""; - - if (boundary != null) { - // boundary needs to start with a character, hence we append apidash - // and remove hyphen characters from the existing boundary - boundary = "apidash_${boundary.replaceAll(RegExp("-"), "")}"; - } - - var rec = getValidRequestUri( - requestModel.url, - requestModel.enabledRequestParams, - ); - - Uri? uri = rec.$1; - - if (uri == null) { - return ""; - } - - var url = stripUriParams(uri); - - result += kStringFaradayRequireStatement; - if (requestModel.hasFormDataContentType && requestModel.hasFileInFormData) { - result += kStringFaradayMultipartRequireStatement; - } - - var templateRequestUrl = jj.Template(kTemplateRequestUrl); - result += templateRequestUrl.render({"url": url}); - - if (requestModel.hasFormData) { - jj.Template payload; - if (requestModel.hasFileInFormData) { - payload = jj.Template(kTemplateFormParamsWithFile); - } else { - payload = jj.Template(kTemplateFormParamsWithoutFile); - } - result += payload.render({"params": requestModel.formDataMapList}); - } else if (requestModel.hasJsonData || requestModel.hasTextData) { - var templateBody = jj.Template(kTemplateBody); - result += templateBody.render({ - "body": requestModel.requestBody, // - "boundary": boundary, - }); - } - - // crreating faraday connection for request - var templateConnection = jj.Template(kTemplateConnection); - result += templateConnection.render({ - "hasFile": requestModel.hasFormDataContentType && requestModel.hasFileInFormData // - }); - - // start of the request sending - var templateRequestStart = jj.Template(kTemplateRequestStart); - result += templateRequestStart.render({ - "method": requestModel.method.name, // - "doesMethodAcceptBody": - kMethodsWithBody.contains(requestModel.method) && requestModel.method != HTTPVerb.delete, // - "containsBody": requestModel.hasBody, // - }); - - if (requestModel.hasFormDataContentType && requestModel.hasFileInFormData) { - var templateRequestOptionsBoundary = jj.Template(kTemplateRequestOptionsBoundary); - result += templateRequestOptionsBoundary.render({"boundary": boundary}); - } - - var headers = requestModel.enabledHeadersMap; - if (requestModel.hasBody && !requestModel.hasContentTypeHeader) { - if (requestModel.hasJsonData || requestModel.hasTextData) { - headers["Content-Type"] = requestModel.requestBodyContentType.header; - } else if (requestModel.hasFormData) { - headers["Content-Type"] = - (requestModel.hasFileInFormData) ? "multipart/form-data" : "application/x-www-form-urlencoded"; - } - } - - if (headers.isNotEmpty) { - var templateRequestHeaders = jj.Template(kTemplateRequestHeaders); - result += templateRequestHeaders.render({"headers": headers}); - } - - if (uri.hasQuery) { - var params = uri.queryParameters; - if (params.isNotEmpty) { - var templateRequestParams = jj.Template(kTemplateRequestParams); - result += templateRequestParams.render({"params": params}); - } - } - - if (requestModel.hasBody && requestModel.method == HTTPVerb.delete) { - result += kStringDeleteRequestBody; - } - - result += kStringRequestEnd; - result += kStringResponse; - return result; - } catch (e) { - return null; - } - } -} diff --git a/lib/consts.dart b/lib/consts.dart index 424d0e77..b0ca77bd 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -282,7 +282,6 @@ enum CodegenLanguage { kotlinOkHttp("Kotlin (okhttp3)", "java", "kt"), pythonRequests("Python (requests)", "python", "py"), pythonHttpClient("Python (http.client)", "python", "py"), - rubyFaraday("Ruby (faraday)", "ruby", "rb"), rustActix("Rust (Actix Client)", "rust", "rs"), rustReqwest("Rust (reqwest)", "rust", "rs"), rustCurl("Rust (curl-rust)", "rust", "rs"), diff --git a/test/codegen/ruby_faraday_codegen_test.dart b/test/codegen/ruby_faraday_codegen_test.dart deleted file mode 100644 index 5f94080c..00000000 --- a/test/codegen/ruby_faraday_codegen_test.dart +++ /dev/null @@ -1,744 +0,0 @@ -import 'package:apidash/codegen/codegen.dart'; -import 'package:apidash/consts.dart'; -import 'package:test/test.dart'; -import '../request_models.dart'; - -void main() { - final codeGen = Codegen(); - - group('GET Request', () { - test('GET 1', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet1, "https"), expectedCode); - }); - - test('GET 2', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/country/data") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| - req.params = { - "code" => "US", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet2, "https"), expectedCode); - }); - - test('GET 3', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/country/data") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| - req.params = { - "code" => "IND", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet3, "https"), expectedCode); - }); - - test('GET 4', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/humanize/social") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| - req.params = { - "num" => "8700000", - "digits" => "3", - "system" => "SS", - "add_space" => "true", - "trailing_zeros" => "true", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet4, "https"), expectedCode); - }); - - test('GET 5', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| - req.headers = { - "User-Agent" => "Test Agent", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet5, "https"), expectedCode); - }); - - test('GET 6', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| - req.headers = { - "User-Agent" => "Test Agent", - } - req.params = { - "raw" => "true", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet6, "https"), expectedCode); - }); - - test('GET 7', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet7, "https"), expectedCode); - }); - - test('GET 8', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| - req.headers = { - "User-Agent" => "Test Agent", - } - req.params = { - "raw" => "true", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet8, "https"), expectedCode); - }); - - test('GET 9', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/humanize/social") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| - req.params = { - "num" => "8700000", - "add_space" => "true", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet9, "https"), expectedCode); - }); - - test('GET 10', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/humanize/social") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| - req.headers = { - "User-Agent" => "Test Agent", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect( - codeGen.getCode( - CodegenLanguage.rubyFaraday, - requestModelGet10, - "https", - ), - expectedCode); - }); - - test('GET 11', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/humanize/social") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| - req.headers = { - "User-Agent" => "Test Agent", - } - req.params = { - "num" => "8700000", - "digits" => "3", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet11, "https"), expectedCode); - }); - - test('GET 12', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/humanize/social") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.get(REQUEST_URL) do |req| -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet12, "https"), expectedCode); - }); - }); - - group('HEAD Request', () { - test('HEAD 1', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.head(REQUEST_URL) do |req| -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelHead1, "https"), expectedCode); - }); - - test('HEAD 2', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("http://api.apidash.dev") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.head(REQUEST_URL) do |req| -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelHead2, "http"), expectedCode); - }); - }); - - group('POST Request', () { - test('POST 1', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/case/lower") - -PAYLOAD = <<-apidash_a5d7a5d09d721f398905c39274c7fa33 -{ -"text": "I LOVE Flutter" -} -apidash_a5d7a5d09d721f398905c39274c7fa33 - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.headers = { - "Content-Type" => "text/plain", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost1, "https", - boundary: "a5d7a5d09d721f398905c39274c7fa33"), - expectedCode); - }); - - test('POST 2', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/case/lower") - -PAYLOAD = <<-apidash_8b9b12a09dc81f398905c39274c7fa33 -{ -"text": "I LOVE Flutter", -"flag": null, -"male": true, -"female": false, -"no": 1.2, -"arr": ["null", "true", "false", null] -} -apidash_8b9b12a09dc81f398905c39274c7fa33 - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.headers = { - "Content-Type" => "application/json", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost2, "https", - boundary: "8b9b12a09dc81f398905c39274c7fa33"), - expectedCode); - }); - - test('POST 3', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/case/lower") - -PAYLOAD = <<-apidash_5c3b98809e3c1f398905c39274c7fa33 -{ -"text": "I LOVE Flutter" -} -apidash_5c3b98809e3c1f398905c39274c7fa33 - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.headers = { - "User-Agent" => "Test Agent", - "Content-Type" => "application/json", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost3, "https", - boundary: "5c3b98809e3c1f398905c39274c7fa33"), - expectedCode); - }); - - test('POST 4', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/io/form") - -PAYLOAD = URI.encode_www_form({ - "text" => "API", - "sep" => "|", - "times" => "3", -}) - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.headers = { - "Content-Type" => "application/x-www-form-urlencoded", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect( - codeGen.getCode( - CodegenLanguage.rubyFaraday, - requestModelPost4, - "https", - ), - expectedCode); - }); - test('POST 5', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/io/form") - -PAYLOAD = URI.encode_www_form({ - "text" => "API", - "sep" => "|", - "times" => "3", -}) - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.headers = { - "User-Agent" => "Test Agent", - "Content-Type" => "application/x-www-form-urlencoded", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost5, "https", boundary: "test"), expectedCode); - }); - test('POST 6', () { - const expectedCode = r"""require 'uri' -require 'faraday' -require 'faraday/multipart' - -REQUEST_URL = URI("https://api.apidash.dev/io/img") - -PAYLOAD = { - "token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"), - "imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"), -} - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter - faraday.request :multipart -end - -response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.options.boundary = "apidash_6f6629609fb41f398905c39274c7fa33" - req.headers = { - "Content-Type" => "multipart/form-data", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost6, "https", - boundary: "6f6629609fb41f398905c39274c7fa33"), - expectedCode); - }); - test('POST 7', () { - const expectedCode = r"""require 'uri' -require 'faraday' -require 'faraday/multipart' - -REQUEST_URL = URI("https://api.apidash.dev/io/img") - -PAYLOAD = { - "token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"), - "imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"), -} - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter - faraday.request :multipart -end - -response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.options.boundary = "apidash_3955fcc0a0b71f398905c39274c7fa33" - req.headers = { - "Content-Type" => "multipart/form-data", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost7, "https", - boundary: "3955fcc0a0b71f398905c39274c7fa33"), - expectedCode); - }); - test('POST 8', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://api.apidash.dev/io/form") - -PAYLOAD = URI.encode_www_form({ - "text" => "API", - "sep" => "|", - "times" => "3", -}) - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.headers = { - "Content-Type" => "application/x-www-form-urlencoded", - } - req.params = { - "size" => "2", - "len" => "3", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost8, "https", boundary: "test"), expectedCode); - }); - test('POST 9', () { - const expectedCode = r"""require 'uri' -require 'faraday' -require 'faraday/multipart' - -REQUEST_URL = URI("https://api.apidash.dev/io/img") - -PAYLOAD = { - "token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"), - "imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"), -} - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter - faraday.request :multipart -end - -response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.options.boundary = "apidash_599e5a20a1361f398905c39274c7fa33" - req.headers = { - "User-Agent" => "Test Agent", - "Keep-Alive" => "true", - "Content-Type" => "multipart/form-data", - } - req.params = { - "size" => "2", - "len" => "3", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost9, "https", - boundary: "599e5a20a1361f398905c39274c7fa33"), - expectedCode); - }); - }); - - group('PUT Request', () { - test('PUT 1', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://reqres.in/api/users/2") - -PAYLOAD = <<-apidash_b4e90990a34b1f398905c39274c7fa33 -{ -"name": "morpheus", -"job": "zion resident" -} -apidash_b4e90990a34b1f398905c39274c7fa33 - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.put(REQUEST_URL, PAYLOAD) do |req| - req.headers = { - "Content-Type" => "application/json", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPut1, "https", - boundary: "b4e90990a34b1f398905c39274c7fa33"), - expectedCode); - }); - }); - - group('PATCH Request', () { - test('PATCH 1', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://reqres.in/api/users/2") - -PAYLOAD = <<-apidash_b2e9a260a3931f398905c39274c7fa33 -{ -"name": "marfeus", -"job": "accountant" -} -apidash_b2e9a260a3931f398905c39274c7fa33 - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.patch(REQUEST_URL, PAYLOAD) do |req| - req.headers = { - "Content-Type" => "application/json", - } -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPatch1, "https", - boundary: "b2e9a260a3931f398905c39274c7fa33"), - expectedCode); - }); - }); - - group('DELETE Request', () { - test('DELETE 1', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://reqres.in/api/users/2") - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.delete(REQUEST_URL) do |req| -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelDelete1, "https"), expectedCode); - }); - - test('DELETE 2', () { - const expectedCode = r"""require 'uri' -require 'faraday' - -REQUEST_URL = URI("https://reqres.in/api/users/2") - -PAYLOAD = <<-apidash_f2291be0a40b1f398905c39274c7fa33 -{ -"name": "marfeus", -"job": "accountant" -} -apidash_f2291be0a40b1f398905c39274c7fa33 - -conn = Faraday.new do |faraday| - faraday.adapter Faraday.default_adapter -end - -response = conn.delete(REQUEST_URL) do |req| - req.headers = { - "Content-Type" => "application/json", - } - req.body = PAYLOAD -end - -puts "Status Code: #{response.status}" -puts "Response Body: #{response.body}" -"""; - expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelDelete2, "https", - boundary: "f2291be0a40b1f398905c39274c7fa33"), - expectedCode); - }); - }); -} From bc89374d1438e060e537c1f9c766ac6e9e71fe35 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 31 Mar 2024 17:34:13 +0530 Subject: [PATCH 114/138] Update codegen.dart --- lib/codegen/codegen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index 76ea70c0..f3f606ae 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -64,7 +64,7 @@ class Codegen { case CodegenLanguage.javaOkHttp: return JavaOkHttpCodeGen().getCode(rM); case CodegenLanguage.juliaHttp: - return JuliaHttpClientCodeGen().getCode(rM, boundary: boundary); + return JuliaHttpClientCodeGen().getCode(rM); case CodegenLanguage.kotlinOkHttp: return KotlinOkHttpCodeGen().getCode(rM); case CodegenLanguage.pythonHttpClient: From e863b35ada2d53b11f649ebd4906b7774afb70a9 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 31 Mar 2024 17:34:32 +0530 Subject: [PATCH 115/138] Update http.dart --- lib/codegen/julia/http.dart | 57 +++++++++++++------------------------ 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/lib/codegen/julia/http.dart b/lib/codegen/julia/http.dart index 04f14047..56ab744e 100644 --- a/lib/codegen/julia/http.dart +++ b/lib/codegen/julia/http.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:jinja/jinja.dart' as jj; -import 'package:apidash/utils/utils.dart' show getNewUuid, getValidRequestUri, stripUriParams; +import 'package:apidash/utils/utils.dart' + show getValidRequestUri, stripUriParams; import 'package:apidash/models/models.dart' show RequestModel; class JuliaHttpClientCodeGen { @@ -12,10 +13,6 @@ using HTTP{% if hasJson %}, JSON{% endif %} final String kTemplateUrl = """ url = "{{url}}" \n -"""; - final String kTemplateBoundary = """ -boundary = "{{boundary}}" -\n """; String kTemplateParams = """ @@ -37,7 +34,7 @@ headers = Dict( """; final String kTemplateFormDataBody = ''' -{{ 'data' if hasFile else 'payload' }} = Dict( +data = Dict( {%- for data in formdata %} {%- if data.type == "text" %} "{{ data.name }}" => "{{ data.value }}", @@ -46,17 +43,15 @@ headers = Dict( {%- endif %} {%- endfor %} ) -{%- if hasFile %} -payload = HTTP.Form(data{% if boundary is defined %}, boundary=boundary{% endif %}) -{%- endif %} +payload = HTTP.Form(data) \n '''; - String kTemplateBody = """ -payload = \"\"\"{{ body }}\"\"\" + String kTemplateBody = ''' +payload = """{{ body }}""" \n -"""; +'''; String kTemplateRequest = """ response = HTTP.request("{{ method | upper }}", url @@ -72,15 +67,15 @@ response = HTTP.request("{{ method | upper }}", url , status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - String? getCode(RequestModel requestModel, {String? boundary}) { + String? getCode(RequestModel requestModel) { try { String result = ""; bool hasQuery = false; bool hasHeaders = false; - bool hasBody = false; + bool addHeaderForBody = false; var rec = getValidRequestUri( requestModel.url, @@ -91,18 +86,13 @@ println("Response Body: \n\n$(String(response.body))") final templateStart = jj.Template(kTemplateStart); result += templateStart.render({ // "hasJson": requestModel.hasBody && requestModel.hasJsonContentType && requestModel.hasJsonData, - "hasJson": false, // we manually send false because we do not require JSON package + "hasJson": + false, // we manually send false because we do not require JSON package }); final templateUrl = jj.Template(kTemplateUrl); result += templateUrl.render({"url": stripUriParams(uri)}); - if (requestModel.hasFormData && requestModel.hasFileInFormData) { - boundary ??= getNewUuid(); - final templateParams = jj.Template(kTemplateBoundary); - result += templateParams.render({"boundary": boundary}); - } - if (uri.hasQuery) { var params = uri.queryParameters; if (params.isNotEmpty) { @@ -113,41 +103,34 @@ println("Response Body: \n\n$(String(response.body))") } if (requestModel.hasJsonData || requestModel.hasTextData) { - hasBody = true; + addHeaderForBody = true; final templateBody = jj.Template(kTemplateBody); var bodyStr = requestModel.requestBody; result += templateBody.render({"body": bodyStr}); } if (requestModel.hasFormData) { - hasBody = true; final formDataBodyData = jj.Template(kTemplateFormDataBody); result += formDataBodyData.render( { "hasFile": requestModel.hasFileInFormData, "formdata": requestModel.formDataMapList, - "boundary": boundary, }, ); } var headersList = requestModel.enabledRequestHeaders; - if (headersList != null || hasBody) { + if (headersList != null || addHeaderForBody) { var headers = requestModel.enabledHeadersMap; if (!requestModel.hasContentTypeHeader) { - if (hasBody) { - headers[HttpHeaders.contentTypeHeader] = requestModel.requestBodyContentType.header; - } - - if (requestModel.hasFormData) { - headers[HttpHeaders.contentTypeHeader] = requestModel.hasFileInFormData - ? "multipart/form-data; boundary=\$(boundary)" - : "application/x-www-form-urlencoded"; + if (addHeaderForBody) { + headers[HttpHeaders.contentTypeHeader] = + requestModel.requestBodyContentType.header; } } - if (headers.isNotEmpty || hasBody) { + if (headers.isNotEmpty) { hasHeaders = true; var templateHeaders = jj.Template(kTemplateHeaders); result += templateHeaders.render({"headers": headers}); @@ -159,11 +142,11 @@ println("Response Body: \n\n$(String(response.body))") "method": requestModel.method.name, }); - if (hasHeaders || requestModel.hasFormData) { + if (hasHeaders) { result += kStringRequestHeaders; } - if (hasBody || requestModel.hasFormData) { + if (requestModel.hasBody) { result += kStringRequestBody; } From 8ad1e1b9f18ba12225d44e346c1d2d922e71cf72 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 31 Mar 2024 17:34:41 +0530 Subject: [PATCH 116/138] Update julia_http_codegen_test.dart --- test/codegen/julia_http_codegen_test.dart | 281 +++++++++++++--------- 1 file changed, 162 insertions(+), 119 deletions(-) diff --git a/test/codegen/julia_http_codegen_test.dart b/test/codegen/julia_http_codegen_test.dart index 68638d3f..eb78e63b 100644 --- a/test/codegen/julia_http_codegen_test.dart +++ b/test/codegen/julia_http_codegen_test.dart @@ -15,9 +15,11 @@ url = "https://api.apidash.dev" response = HTTP.request("GET", url, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet1, "https"), expectedCode); + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet1, "https"), + expectedCode); }); test('GET 2', () { const expectedCode = r"""using HTTP @@ -31,9 +33,11 @@ params = Dict( response = HTTP.request("GET", url, query=params, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet2, "https"), expectedCode); + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet2, "https"), + expectedCode); }); test('GET 3', () { const expectedCode = r"""using HTTP @@ -47,9 +51,11 @@ params = Dict( response = HTTP.request("GET", url, query=params, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet3, "https"), expectedCode); + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet3, "https"), + expectedCode); }); test('GET 4', () { const expectedCode = r"""using HTTP @@ -67,9 +73,11 @@ params = Dict( response = HTTP.request("GET", url, query=params, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet4, "https"), expectedCode); + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet4, "https"), + expectedCode); }); test('GET 5', () { @@ -84,9 +92,11 @@ headers = Dict( response = HTTP.request("GET", url, headers=headers, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet5, "https"), expectedCode); + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet5, "https"), + expectedCode); }); test('GET 6', () { @@ -105,9 +115,11 @@ headers = Dict( response = HTTP.request("GET", url, headers=headers, query=params, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet6, "https"), expectedCode); + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet6, "https"), + expectedCode); }); test('GET 7', () { @@ -118,9 +130,11 @@ url = "https://api.apidash.dev" response = HTTP.request("GET", url, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet7, "https"), expectedCode); + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet7, "https"), + expectedCode); }); test('GET 8', () { @@ -139,9 +153,11 @@ headers = Dict( response = HTTP.request("GET", url, headers=headers, query=params, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet8, "https"), expectedCode); + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet8, "https"), + expectedCode); }); test('GET 9', () { @@ -157,9 +173,11 @@ params = Dict( response = HTTP.request("GET", url, query=params, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet9, "https"), expectedCode); + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet9, "https"), + expectedCode); }); test('GET 10', () { @@ -174,9 +192,12 @@ headers = Dict( response = HTTP.request("GET", url, headers=headers, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet10, "https"), expectedCode); + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelGet10, "https"), + expectedCode); }); test('GET 11', () { @@ -196,9 +217,12 @@ headers = Dict( response = HTTP.request("GET", url, headers=headers, query=params, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet11, "https"), expectedCode); + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelGet11, "https"), + expectedCode); }); test('GET 12', () { @@ -209,9 +233,12 @@ url = "https://api.apidash.dev/humanize/social" response = HTTP.request("GET", url, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet12, "https"), expectedCode); + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelGet12, "https"), + expectedCode); }); }); @@ -224,9 +251,12 @@ url = "https://api.apidash.dev" response = HTTP.request("HEAD", url, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelHead1, "https"), expectedCode); + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelHead1, "https"), + expectedCode); }); test('HEAD 2', () { @@ -237,21 +267,23 @@ url = "http://api.apidash.dev" response = HTTP.request("HEAD", url, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelHead2, "http"), expectedCode); + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelHead2, "http"), + expectedCode); }); }); group('POST Request', () { test('POST 1', () { - const expectedCode = """using HTTP + const expectedCode = r'''using HTTP url = "https://api.apidash.dev/case/lower" -payload = \"\"\"{ +payload = """{ "text": "I LOVE Flutter" -}\"\"\" +}""" headers = Dict( "content-type" => "text/plain", @@ -259,25 +291,28 @@ headers = Dict( response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) -println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \\n\\n\$(String(response.body))") -"""; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost1, "https"), expectedCode); +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n$(String(response.body))") +'''; + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelPost1, "https"), + expectedCode); }); test('POST 2', () { - const expectedCode = """using HTTP + const expectedCode = r'''using HTTP url = "https://api.apidash.dev/case/lower" -payload = \"\"\"{ +payload = """{ "text": "I LOVE Flutter", "flag": null, "male": true, "female": false, "no": 1.2, "arr": ["null", "true", "false", null] -}\"\"\" +}""" headers = Dict( "content-type" => "application/json", @@ -285,19 +320,22 @@ headers = Dict( response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) -println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \\n\\n\$(String(response.body))") -"""; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost2, "https"), expectedCode); +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n$(String(response.body))") +'''; + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelPost2, "https"), + expectedCode); }); test('POST 3', () { - const expectedCode = """using HTTP + const expectedCode = r'''using HTTP url = "https://api.apidash.dev/case/lower" -payload = \"\"\"{ +payload = """{ "text": "I LOVE Flutter" -}\"\"\" +}""" headers = Dict( "User-Agent" => "Test Agent", @@ -306,10 +344,13 @@ headers = Dict( response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) -println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \\n\\n\$(String(response.body))") -"""; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost3, "https"), expectedCode); +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n$(String(response.body))") +'''; + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelPost3, "https"), + expectedCode); }); test('POST 4', () { @@ -317,22 +358,23 @@ println("Response Body: \\n\\n\$(String(response.body))") url = "https://api.apidash.dev/io/form" -payload = Dict( +data = Dict( "text" => "API", "sep" => "|", "times" => "3", ) -headers = Dict( - "content-type" => "application/x-www-form-urlencoded", -) +payload = HTTP.Form(data) -response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) +response = HTTP.request("POST", url, body=payload, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost4, "https"), expectedCode); + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelPost4, "https"), + expectedCode); }); test('POST 5', () { @@ -340,50 +382,48 @@ println("Response Body: \n\n$(String(response.body))") url = "https://api.apidash.dev/io/form" -payload = Dict( +data = Dict( "text" => "API", "sep" => "|", "times" => "3", ) +payload = HTTP.Form(data) + headers = Dict( "User-Agent" => "Test Agent", - "content-type" => "application/x-www-form-urlencoded", ) response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost5, "https"), expectedCode); + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelPost5, "https"), + expectedCode); }); test('POST 6', () { const expectedCode = r"""using HTTP url = "https://api.apidash.dev/io/img" -boundary = "467fbea0-c2dc-1f41-b12d-9d9923a5f7b8" - data = Dict( "token" => "xyz", "imfile" => open("/Documents/up/1.png"), ) -payload = HTTP.Form(data, boundary=boundary) +payload = HTTP.Form(data) -headers = Dict( - "content-type" => "multipart/form-data; boundary=$(boundary)", -) - -response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) +response = HTTP.request("POST", url, body=payload, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost6, "https", - boundary: "467fbea0-c2dc-1f41-b12d-9d9923a5f7b8"), + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelPost6, "https"), expectedCode); }); test('POST 7', () { @@ -391,27 +431,21 @@ println("Response Body: \n\n$(String(response.body))") url = "https://api.apidash.dev/io/img" -boundary = "9440cbe0-c433-1f41-b12d-9d9923a5f7b8" - data = Dict( "token" => "xyz", "imfile" => open("/Documents/up/1.png"), ) -payload = HTTP.Form(data, boundary=boundary) +payload = HTTP.Form(data) -headers = Dict( - "content-type" => "multipart/form-data; boundary=$(boundary)", -) - -response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false) +response = HTTP.request("POST", url, body=payload, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost7, "https", - boundary: "9440cbe0-c433-1f41-b12d-9d9923a5f7b8"), + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelPost7, "https"), expectedCode); }); test('POST 8', () { @@ -424,30 +458,29 @@ params = Dict( "len" => "3", ) -payload = Dict( +data = Dict( "text" => "API", "sep" => "|", "times" => "3", ) -headers = Dict( - "content-type" => "application/x-www-form-urlencoded", -) +payload = HTTP.Form(data) -response = HTTP.request("POST", url, headers=headers, body=payload, query=params, status_exception=false) +response = HTTP.request("POST", url, body=payload, query=params, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost8, "https"), expectedCode); + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelPost8, "https"), + expectedCode); }); test('POST 9', () { const expectedCode = r"""using HTTP url = "https://api.apidash.dev/io/img" -boundary = "69573b00-c67f-1f41-b12d-9d9923a5f7b8" - params = Dict( "size" => "2", "len" => "3", @@ -458,35 +491,34 @@ data = Dict( "imfile" => open("/Documents/up/1.png"), ) -payload = HTTP.Form(data, boundary=boundary) +payload = HTTP.Form(data) headers = Dict( "User-Agent" => "Test Agent", "Keep-Alive" => "true", - "content-type" => "multipart/form-data; boundary=$(boundary)", ) response = HTTP.request("POST", url, headers=headers, body=payload, query=params, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; expect( - codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPost9, "https", - boundary: "69573b00-c67f-1f41-b12d-9d9923a5f7b8"), + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelPost9, "https"), expectedCode); }); }); group('PUT Request', () { test('PUT 1', () { - const expectedCode = """using HTTP + const expectedCode = r'''using HTTP url = "https://reqres.in/api/users/2" -payload = \"\"\"{ +payload = """{ "name": "morpheus", "job": "zion resident" -}\"\"\" +}""" headers = Dict( "content-type" => "application/json", @@ -494,22 +526,24 @@ headers = Dict( response = HTTP.request("PUT", url, headers=headers, body=payload, status_exception=false) -println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \\n\\n\$(String(response.body))") -"""; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPut1, "https"), expectedCode); +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n$(String(response.body))") +'''; + expect( + codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPut1, "https"), + expectedCode); }); }); group('PATCH Request', () { test('PATCH 1', () { - const expectedCode = """using HTTP + const expectedCode = r'''using HTTP url = "https://reqres.in/api/users/2" -payload = \"\"\"{ +payload = """{ "name": "marfeus", "job": "accountant" -}\"\"\" +}""" headers = Dict( "content-type" => "application/json", @@ -517,10 +551,13 @@ headers = Dict( response = HTTP.request("PATCH", url, headers=headers, body=payload, status_exception=false) -println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \\n\\n\$(String(response.body))") -"""; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPatch1, "https"), expectedCode); +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n$(String(response.body))") +'''; + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelPatch1, "https"), + expectedCode); }); }); group('DELETE Request', () { @@ -532,19 +569,22 @@ url = "https://reqres.in/api/users/2" response = HTTP.request("DELETE", url, status_exception=false) println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \n\n$(String(response.body))") +println("Response Body: \n$(String(response.body))") """; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelDelete1, "https"), expectedCode); + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelDelete1, "https"), + expectedCode); }); test('DELETE 2', () { - const expectedCode = """using HTTP + const expectedCode = r'''using HTTP url = "https://reqres.in/api/users/2" -payload = \"\"\"{ +payload = """{ "name": "marfeus", "job": "accountant" -}\"\"\" +}""" headers = Dict( "content-type" => "application/json", @@ -552,10 +592,13 @@ headers = Dict( response = HTTP.request("DELETE", url, headers=headers, body=payload, status_exception=false) -println("Status Code: \$(response.status) \$(HTTP.StatusCodes.statustext(response.status))") -println("Response Body: \\n\\n\$(String(response.body))") -"""; - expect(codeGen.getCode(CodegenLanguage.juliaHttp, requestModelDelete2, "https"), expectedCode); +println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))") +println("Response Body: \n$(String(response.body))") +'''; + expect( + codeGen.getCode( + CodegenLanguage.juliaHttp, requestModelDelete2, "https"), + expectedCode); }); }); } From bc6dab72120bcf24b805333e9eb06863f86e696f Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 31 Mar 2024 17:37:21 +0530 Subject: [PATCH 117/138] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3297c14e..be6c6a30 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ API Dash currently supports API integration code generation for the following la | Java | `asynchttpclient` | https://github.com/foss42/apidash/issues/136 | | Java | `HttpClient` | https://github.com/foss42/apidash/issues/137 | | Java | `okhttp3` | | -| Julia | `HTTP` | https://github.com/foss42/apidash/issues/154 | +| Julia | `HTTP` | | | PHP | `guzzle` | https://github.com/foss42/apidash/issues/143 | We welcome contributions to support other programming languages/libraries/frameworks. Please check out more details [here](https://github.com/foss42/apidash/discussions/80). From e6b4ef071a07f725c0a6cf2a033fddb8f25994eb Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sun, 31 Mar 2024 19:27:37 +0530 Subject: [PATCH 118/138] added ruby faraday as constant --- lib/consts.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/consts.dart b/lib/consts.dart index b0ca77bd..017e5f10 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -282,6 +282,7 @@ enum CodegenLanguage { kotlinOkHttp("Kotlin (okhttp3)", "java", "kt"), pythonRequests("Python (requests)", "python", "py"), pythonHttpClient("Python (http.client)", "python", "py"), + rubyFaraday("Ruby (Faraday)", "ruby", "rb"), rustActix("Rust (Actix Client)", "rust", "rs"), rustReqwest("Rust (reqwest)", "rust", "rs"), rustCurl("Rust (curl-rust)", "rust", "rs"), From aa535a4d8d16fb109ca9c9f0bd7313bcc7bc1254 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sun, 31 Mar 2024 19:28:17 +0530 Subject: [PATCH 119/138] added code generator support ruby faraday --- lib/codegen/codegen.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index f3f606ae..90fea8fa 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -8,6 +8,7 @@ import 'kotlin/okhttp.dart'; import 'php/guzzle.dart'; import 'python/http_client.dart'; import 'python/requests.dart'; +import 'ruby/faraday.dart'; import 'rust/actix.dart'; import 'rust/curl_rust.dart'; import 'rust/reqwest.dart'; @@ -72,6 +73,8 @@ class Codegen { .getCode(rM, boundary: boundary ?? getNewUuid()); case CodegenLanguage.pythonRequests: return PythonRequestsCodeGen().getCode(rM, boundary: boundary); + case CodegenLanguage.rubyFaraday: + return RubyFaradayCodeGen().getCode(rM, boundary: boundary ?? getNewUuid()); case CodegenLanguage.rustActix: return RustActixCodeGen().getCode(rM, boundary: boundary); case CodegenLanguage.rustCurl: From b86adacffcfce660b81b3f6c4ea0ab3e858a18fa Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sun, 31 Mar 2024 19:29:00 +0530 Subject: [PATCH 120/138] addec class for generating faraday code --- lib/codegen/ruby/faraday.dart | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 lib/codegen/ruby/faraday.dart diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart new file mode 100644 index 00000000..a01c0719 --- /dev/null +++ b/lib/codegen/ruby/faraday.dart @@ -0,0 +1,14 @@ +import 'package:apidash/consts.dart'; +import 'package:jinja/jinja.dart' as jj; +import 'package:apidash/utils/utils.dart' show getValidRequestUri; +import 'package:apidash/utils/http_utils.dart' show stripUriParams; + +import 'package:apidash/models/models.dart' show RequestModel; + +// Note that delete is a special case in Faraday as API Dash supports request +// body inside delete reqest, but Faraday does not. Hence we need to manually +// setup request body for delete request and add that to request. +// +// Refer https://lostisland.github.io/faraday/#/getting-started/quick-start?id=get-head-delete-trace +class RubyFaradayCodeGen { +} From 2671f61eb344f0c426ecb7e82aa4fdb33a751fac Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sun, 31 Mar 2024 19:29:18 +0530 Subject: [PATCH 121/138] added templates for faraday code --- lib/codegen/ruby/faraday.dart | 65 +++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index a01c0719..043f1387 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -11,4 +11,69 @@ import 'package:apidash/models/models.dart' show RequestModel; // // Refer https://lostisland.github.io/faraday/#/getting-started/quick-start?id=get-head-delete-trace class RubyFaradayCodeGen { + final String kStringFaradayRequireStatement = """ +require 'uri' +require 'faraday' +"""; + + final String kStringFaradayMultipartRequireStatement = ''' +require 'faraday/multipart' +'''; + + final String kTemplateRequestUrl = """ +\nREQUEST_URL = URI("{{ url }}")\n\n +"""; + + final String kTemplateBody = """ +PAYLOAD = <<-{{ boundary }} +{{ body }} +{{ boundary }}\n\n +"""; + + final String kTemplateFormParamsWithFile = """ +PAYLOAD = { +{% for param in params %}{% if param.type == "text" %} "{{ param.name }}" => Faraday::Multipart::ParamPart.new("{{ param.value }}", "text/plain"), +{% elif param.type == "file" %} "{{ param.name }}" => Faraday::Multipart::FilePart.new("{{ param.value }}", "application/octet-stream"),{% endif %}{% endfor %} +}\n\n +"""; + + final String kTemplateFormParamsWithoutFile = """ +PAYLOAD = URI.encode_www_form({\n{% for param in params %} "{{ param.name }}" => "{{ param.value }}",\n{% endfor %}})\n\n +"""; + + final String kTemplateConnection = """ +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter{% if hasFile %}\n faraday.request :multipart{% endif %} +end\n\n +"""; + + final String kTemplateRequestStart = """ +response = conn.{{ method|lower }}(REQUEST_URL{% if doesMethodAcceptBody and containsBody %}, PAYLOAD{% endif %}) do |req|\n +"""; + + final String kTemplateRequestOptionsBoundary = """ + req.options.boundary = "{{ boundary }}"\n +"""; + + final String kTemplateRequestParams = """ + req.params = {\n{% for key, val in params %} "{{ key }}" => "{{ val }}",\n{% endfor %} }\n +"""; + + final String kTemplateRequestHeaders = """ + req.headers = {\n{% for key, val in headers %} "{{ key }}" => "{{ val }}",\n{% endfor %} }\n +"""; + + final String kStringDeleteRequestBody = """ + req.body = PAYLOAD +"""; + + final String kStringRequestEnd = """ +end\n +"""; + + final String kStringResponse = """ +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + } From 67155a81298cb518d827319245bef10f7bac5d91 Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sun, 31 Mar 2024 19:29:38 +0530 Subject: [PATCH 122/138] added code generator for faraday --- lib/codegen/ruby/faraday.dart | 104 ++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index 043f1387..04c166f0 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -76,4 +76,108 @@ puts "Status Code: #{response.status}" puts "Response Body: #{response.body}" """; + String? getCode( + RequestModel requestModel, { + String? boundary, + }) { + try { + String result = ""; + + if (boundary != null) { + // boundary needs to start with a character, hence we append apidash + // and remove hyphen characters from the existing boundary + boundary = "apidash_${boundary.replaceAll(RegExp("-"), "")}"; + } + + var rec = getValidRequestUri( + requestModel.url, + requestModel.enabledRequestParams, + ); + + Uri? uri = rec.$1; + + if (uri == null) { + return ""; + } + + var url = stripUriParams(uri); + + result += kStringFaradayRequireStatement; + if (requestModel.hasFormDataContentType && requestModel.hasFileInFormData) { + result += kStringFaradayMultipartRequireStatement; + } + + var templateRequestUrl = jj.Template(kTemplateRequestUrl); + result += templateRequestUrl.render({"url": url}); + + if (requestModel.hasFormData) { + jj.Template payload; + if (requestModel.hasFileInFormData) { + payload = jj.Template(kTemplateFormParamsWithFile); + } else { + payload = jj.Template(kTemplateFormParamsWithoutFile); + } + result += payload.render({"params": requestModel.formDataMapList}); + } else if (requestModel.hasJsonData || requestModel.hasTextData) { + var templateBody = jj.Template(kTemplateBody); + result += templateBody.render({ + "body": requestModel.requestBody, // + "boundary": boundary, + }); + } + + // crreating faraday connection for request + var templateConnection = jj.Template(kTemplateConnection); + result += templateConnection.render({ + "hasFile": requestModel.hasFormDataContentType && requestModel.hasFileInFormData // + }); + + // start of the request sending + var templateRequestStart = jj.Template(kTemplateRequestStart); + result += templateRequestStart.render({ + "method": requestModel.method.name, // + "doesMethodAcceptBody": + kMethodsWithBody.contains(requestModel.method) && requestModel.method != HTTPVerb.delete, // + "containsBody": requestModel.hasBody, // + }); + + if (requestModel.hasFormDataContentType && requestModel.hasFileInFormData) { + var templateRequestOptionsBoundary = jj.Template(kTemplateRequestOptionsBoundary); + result += templateRequestOptionsBoundary.render({"boundary": boundary}); + } + + var headers = requestModel.enabledHeadersMap; + if (requestModel.hasBody && !requestModel.hasContentTypeHeader) { + if (requestModel.hasJsonData || requestModel.hasTextData) { + headers["Content-Type"] = requestModel.requestBodyContentType.header; + } else if (requestModel.hasFormData) { + headers["Content-Type"] = + (requestModel.hasFileInFormData) ? "multipart/form-data" : "application/x-www-form-urlencoded"; + } + } + + if (headers.isNotEmpty) { + var templateRequestHeaders = jj.Template(kTemplateRequestHeaders); + result += templateRequestHeaders.render({"headers": headers}); + } + + if (uri.hasQuery) { + var params = uri.queryParameters; + if (params.isNotEmpty) { + var templateRequestParams = jj.Template(kTemplateRequestParams); + result += templateRequestParams.render({"params": params}); + } + } + + if (requestModel.hasBody && requestModel.method == HTTPVerb.delete) { + result += kStringDeleteRequestBody; + } + + result += kStringRequestEnd; + result += kStringResponse; + return result; + } catch (e) { + return null; + } + } } From 37eb188cc3ed53b944d58d0b07539d43fd601d7d Mon Sep 17 00:00:00 2001 From: adityamayukhsom Date: Sun, 31 Mar 2024 19:29:50 +0530 Subject: [PATCH 123/138] added tests for faraday code generator --- test/codegen/ruby_faraday_codegen_test.dart | 744 ++++++++++++++++++++ 1 file changed, 744 insertions(+) create mode 100644 test/codegen/ruby_faraday_codegen_test.dart diff --git a/test/codegen/ruby_faraday_codegen_test.dart b/test/codegen/ruby_faraday_codegen_test.dart new file mode 100644 index 00000000..5f94080c --- /dev/null +++ b/test/codegen/ruby_faraday_codegen_test.dart @@ -0,0 +1,744 @@ +import 'package:apidash/codegen/codegen.dart'; +import 'package:apidash/consts.dart'; +import 'package:test/test.dart'; +import '../request_models.dart'; + +void main() { + final codeGen = Codegen(); + + group('GET Request', () { + test('GET 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet1, "https"), expectedCode); + }); + + test('GET 2', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/country/data") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.params = { + "code" => "US", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet2, "https"), expectedCode); + }); + + test('GET 3', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/country/data") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.params = { + "code" => "IND", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet3, "https"), expectedCode); + }); + + test('GET 4', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/humanize/social") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.params = { + "num" => "8700000", + "digits" => "3", + "system" => "SS", + "add_space" => "true", + "trailing_zeros" => "true", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet4, "https"), expectedCode); + }); + + test('GET 5', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.headers = { + "User-Agent" => "Test Agent", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet5, "https"), expectedCode); + }); + + test('GET 6', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.headers = { + "User-Agent" => "Test Agent", + } + req.params = { + "raw" => "true", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet6, "https"), expectedCode); + }); + + test('GET 7', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet7, "https"), expectedCode); + }); + + test('GET 8', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.headers = { + "User-Agent" => "Test Agent", + } + req.params = { + "raw" => "true", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet8, "https"), expectedCode); + }); + + test('GET 9', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/humanize/social") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.params = { + "num" => "8700000", + "add_space" => "true", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet9, "https"), expectedCode); + }); + + test('GET 10', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/humanize/social") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.headers = { + "User-Agent" => "Test Agent", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode( + CodegenLanguage.rubyFaraday, + requestModelGet10, + "https", + ), + expectedCode); + }); + + test('GET 11', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/humanize/social") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| + req.headers = { + "User-Agent" => "Test Agent", + } + req.params = { + "num" => "8700000", + "digits" => "3", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet11, "https"), expectedCode); + }); + + test('GET 12', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/humanize/social") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.get(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet12, "https"), expectedCode); + }); + }); + + group('HEAD Request', () { + test('HEAD 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.head(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelHead1, "https"), expectedCode); + }); + + test('HEAD 2', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("http://api.apidash.dev") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.head(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelHead2, "http"), expectedCode); + }); + }); + + group('POST Request', () { + test('POST 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/case/lower") + +PAYLOAD = <<-apidash_a5d7a5d09d721f398905c39274c7fa33 +{ +"text": "I LOVE Flutter" +} +apidash_a5d7a5d09d721f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "text/plain", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost1, "https", + boundary: "a5d7a5d09d721f398905c39274c7fa33"), + expectedCode); + }); + + test('POST 2', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/case/lower") + +PAYLOAD = <<-apidash_8b9b12a09dc81f398905c39274c7fa33 +{ +"text": "I LOVE Flutter", +"flag": null, +"male": true, +"female": false, +"no": 1.2, +"arr": ["null", "true", "false", null] +} +apidash_8b9b12a09dc81f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "application/json", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost2, "https", + boundary: "8b9b12a09dc81f398905c39274c7fa33"), + expectedCode); + }); + + test('POST 3', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/case/lower") + +PAYLOAD = <<-apidash_5c3b98809e3c1f398905c39274c7fa33 +{ +"text": "I LOVE Flutter" +} +apidash_5c3b98809e3c1f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "User-Agent" => "Test Agent", + "Content-Type" => "application/json", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost3, "https", + boundary: "5c3b98809e3c1f398905c39274c7fa33"), + expectedCode); + }); + + test('POST 4', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/io/form") + +PAYLOAD = URI.encode_www_form({ + "text" => "API", + "sep" => "|", + "times" => "3", +}) + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "application/x-www-form-urlencoded", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode( + CodegenLanguage.rubyFaraday, + requestModelPost4, + "https", + ), + expectedCode); + }); + test('POST 5', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/io/form") + +PAYLOAD = URI.encode_www_form({ + "text" => "API", + "sep" => "|", + "times" => "3", +}) + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "User-Agent" => "Test Agent", + "Content-Type" => "application/x-www-form-urlencoded", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost5, "https", boundary: "test"), expectedCode); + }); + test('POST 6', () { + const expectedCode = r"""require 'uri' +require 'faraday' +require 'faraday/multipart' + +REQUEST_URL = URI("https://api.apidash.dev/io/img") + +PAYLOAD = { + "token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"), + "imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"), +} + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter + faraday.request :multipart +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.options.boundary = "apidash_6f6629609fb41f398905c39274c7fa33" + req.headers = { + "Content-Type" => "multipart/form-data", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost6, "https", + boundary: "6f6629609fb41f398905c39274c7fa33"), + expectedCode); + }); + test('POST 7', () { + const expectedCode = r"""require 'uri' +require 'faraday' +require 'faraday/multipart' + +REQUEST_URL = URI("https://api.apidash.dev/io/img") + +PAYLOAD = { + "token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"), + "imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"), +} + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter + faraday.request :multipart +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.options.boundary = "apidash_3955fcc0a0b71f398905c39274c7fa33" + req.headers = { + "Content-Type" => "multipart/form-data", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost7, "https", + boundary: "3955fcc0a0b71f398905c39274c7fa33"), + expectedCode); + }); + test('POST 8', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://api.apidash.dev/io/form") + +PAYLOAD = URI.encode_www_form({ + "text" => "API", + "sep" => "|", + "times" => "3", +}) + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "application/x-www-form-urlencoded", + } + req.params = { + "size" => "2", + "len" => "3", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost8, "https", boundary: "test"), expectedCode); + }); + test('POST 9', () { + const expectedCode = r"""require 'uri' +require 'faraday' +require 'faraday/multipart' + +REQUEST_URL = URI("https://api.apidash.dev/io/img") + +PAYLOAD = { + "token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"), + "imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"), +} + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter + faraday.request :multipart +end + +response = conn.post(REQUEST_URL, PAYLOAD) do |req| + req.options.boundary = "apidash_599e5a20a1361f398905c39274c7fa33" + req.headers = { + "User-Agent" => "Test Agent", + "Keep-Alive" => "true", + "Content-Type" => "multipart/form-data", + } + req.params = { + "size" => "2", + "len" => "3", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost9, "https", + boundary: "599e5a20a1361f398905c39274c7fa33"), + expectedCode); + }); + }); + + group('PUT Request', () { + test('PUT 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://reqres.in/api/users/2") + +PAYLOAD = <<-apidash_b4e90990a34b1f398905c39274c7fa33 +{ +"name": "morpheus", +"job": "zion resident" +} +apidash_b4e90990a34b1f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.put(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "application/json", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPut1, "https", + boundary: "b4e90990a34b1f398905c39274c7fa33"), + expectedCode); + }); + }); + + group('PATCH Request', () { + test('PATCH 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://reqres.in/api/users/2") + +PAYLOAD = <<-apidash_b2e9a260a3931f398905c39274c7fa33 +{ +"name": "marfeus", +"job": "accountant" +} +apidash_b2e9a260a3931f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.patch(REQUEST_URL, PAYLOAD) do |req| + req.headers = { + "Content-Type" => "application/json", + } +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPatch1, "https", + boundary: "b2e9a260a3931f398905c39274c7fa33"), + expectedCode); + }); + }); + + group('DELETE Request', () { + test('DELETE 1', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://reqres.in/api/users/2") + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.delete(REQUEST_URL) do |req| +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelDelete1, "https"), expectedCode); + }); + + test('DELETE 2', () { + const expectedCode = r"""require 'uri' +require 'faraday' + +REQUEST_URL = URI("https://reqres.in/api/users/2") + +PAYLOAD = <<-apidash_f2291be0a40b1f398905c39274c7fa33 +{ +"name": "marfeus", +"job": "accountant" +} +apidash_f2291be0a40b1f398905c39274c7fa33 + +conn = Faraday.new do |faraday| + faraday.adapter Faraday.default_adapter +end + +response = conn.delete(REQUEST_URL) do |req| + req.headers = { + "Content-Type" => "application/json", + } + req.body = PAYLOAD +end + +puts "Status Code: #{response.status}" +puts "Response Body: #{response.body}" +"""; + expect( + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelDelete2, "https", + boundary: "f2291be0a40b1f398905c39274c7fa33"), + expectedCode); + }); + }); +} From 0de76cc1f020a1ae481e789edae780ca104183ec Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 31 Mar 2024 19:39:22 +0530 Subject: [PATCH 124/138] print int status code --- lib/codegen/csharp/rest_sharp.dart | 2 +- .../csharp_rest_sharp_codgen_test.dart | 54 +++++++++---------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/codegen/csharp/rest_sharp.dart b/lib/codegen/csharp/rest_sharp.dart index 18a7219b..4d53e685 100644 --- a/lib/codegen/csharp/rest_sharp.dart +++ b/lib/codegen/csharp/rest_sharp.dart @@ -56,7 +56,7 @@ class Program String kStringEnd = """ var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ diff --git a/test/codegen/csharp_rest_sharp_codgen_test.dart b/test/codegen/csharp_rest_sharp_codgen_test.dart index e3d83628..852ef906 100644 --- a/test/codegen/csharp_rest_sharp_codgen_test.dart +++ b/test/codegen/csharp_rest_sharp_codgen_test.dart @@ -22,7 +22,7 @@ class Program var request = new RestRequest("", Method.Get); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -55,7 +55,7 @@ class Program request.AddQueryParameter("code", "US"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -89,7 +89,7 @@ class Program request.AddQueryParameter("code", "IND"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -127,7 +127,7 @@ class Program request.AddQueryParameter("trailing_zeros", "true"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -161,7 +161,7 @@ class Program request.AddHeader("User-Agent", "Test Agent"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -197,7 +197,7 @@ class Program request.AddHeader("User-Agent", "Test Agent"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -229,7 +229,7 @@ class Program var request = new RestRequest("", Method.Get); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -265,7 +265,7 @@ class Program request.AddHeader("User-Agent", "Test Agent"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -299,7 +299,7 @@ class Program request.AddQueryParameter("add_space", "true"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -332,7 +332,7 @@ class Program request.AddHeader("User-Agent", "Test Agent"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -368,7 +368,7 @@ class Program request.AddHeader("User-Agent", "Test Agent"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -399,7 +399,7 @@ class Program var request = new RestRequest("/humanize/social", Method.Get); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -432,7 +432,7 @@ class Program var request = new RestRequest("", Method.Head); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -463,7 +463,7 @@ class Program var request = new RestRequest("", Method.Head); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -503,7 +503,7 @@ class Program request.AddStringBody(textBody); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -545,7 +545,7 @@ class Program request.AddJsonBody(jsonBody); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -583,7 +583,7 @@ class Program request.AddJsonBody(jsonBody); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -619,7 +619,7 @@ class Program request.AddParameter("times", "3", ParameterType.RequestBody); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -656,7 +656,7 @@ class Program request.AddParameter("times", "3", ParameterType.RequestBody); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -691,7 +691,7 @@ class Program request.AddFile("imfile", "/Documents/up/1.png"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -726,7 +726,7 @@ class Program request.AddFile("imfile", "/Documents/up/1.png"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -765,7 +765,7 @@ class Program request.AddParameter("times", "3", ParameterType.RequestBody); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -805,7 +805,7 @@ class Program request.AddFile("imfile", "/Documents/up/1.png"); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -846,7 +846,7 @@ class Program request.AddJsonBody(jsonBody); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -887,7 +887,7 @@ class Program request.AddJsonBody(jsonBody); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -920,7 +920,7 @@ class Program var request = new RestRequest("/api/users/2", Method.Delete); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ @@ -958,7 +958,7 @@ class Program request.AddJsonBody(jsonBody); var response = await client.ExecuteAsync(request); - Console.WriteLine("Status Code: " + response.StatusCode); + Console.WriteLine("Status Code: " + (int)response.StatusCode); Console.WriteLine("Response Content: " + response.Content); } catch(Exception ex){ From 4b1d8bdd03277d55b380df99262fb10dfc82e9d9 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 31 Mar 2024 20:06:36 +0530 Subject: [PATCH 125/138] Update java_httpclient_codegen_test.dart --- .../codegen/java_httpclient_codegen_test.dart | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/test/codegen/java_httpclient_codegen_test.dart b/test/codegen/java_httpclient_codegen_test.dart index 0fc25e2a..d279f5ab 100644 --- a/test/codegen/java_httpclient_codegen_test.dart +++ b/test/codegen/java_httpclient_codegen_test.dart @@ -414,7 +414,7 @@ public class Main { public static void main(String[] args) { try { HttpClient client = HttpClient.newHttpClient(); - URI uri = URI.create("https://api.apidash.dev"); + URI uri = URI.create("http://api.apidash.dev"); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("HEAD", HttpRequest.BodyPublishers.noBody()); HttpResponse response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); @@ -610,7 +610,8 @@ public class Main { }'''; expect( codeGen.getCode( - CodegenLanguage.javaHttpClient, requestModelPost4, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + CodegenLanguage.javaHttpClient, requestModelPost4, "https", + boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), expectedCode); }); test('POST5', () { @@ -679,7 +680,8 @@ public class Main { }'''; expect( codeGen.getCode( - CodegenLanguage.javaHttpClient, requestModelPost5, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + CodegenLanguage.javaHttpClient, requestModelPost5, "https", + boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), expectedCode); }); test('POST6', () { @@ -746,7 +748,8 @@ public class Main { }'''; expect( codeGen.getCode( - CodegenLanguage.javaHttpClient, requestModelPost6, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + CodegenLanguage.javaHttpClient, requestModelPost6, "https", + boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), expectedCode); }); test('POST7', () { @@ -813,7 +816,8 @@ public class Main { }'''; expect( codeGen.getCode( - CodegenLanguage.javaHttpClient, requestModelPost7, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + CodegenLanguage.javaHttpClient, requestModelPost7, "https", + boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), expectedCode); }); test('POST8', () { @@ -881,7 +885,8 @@ public class Main { }'''; expect( codeGen.getCode( - CodegenLanguage.javaHttpClient, requestModelPost8, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + CodegenLanguage.javaHttpClient, requestModelPost8, "https", + boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), expectedCode); }); test('POST9', () { @@ -950,7 +955,8 @@ public class Main { }'''; expect( codeGen.getCode( - CodegenLanguage.javaHttpClient, requestModelPost9, "https", boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), + CodegenLanguage.javaHttpClient, requestModelPost9, "https", + boundary: "b9826c20-773c-1f0c-814d-a1b3d90cd6b3"), expectedCode); }); }); @@ -1100,5 +1106,4 @@ public class Main { expectedCode); }); }); - } From 2ed7f2c5f4ccbebd1ce645b1fe476d6097d40a72 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 31 Mar 2024 20:08:05 +0530 Subject: [PATCH 126/138] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index be6c6a30..6f9bcd25 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ API Dash currently supports API integration code generation for the following la | Rust | `ureq` | | | Rust | `Actix Client` | | | Java | `asynchttpclient` | https://github.com/foss42/apidash/issues/136 | -| Java | `HttpClient` | https://github.com/foss42/apidash/issues/137 | +| Java | `HttpClient` | | | Java | `okhttp3` | | | Julia | `HTTP` | | | PHP | `guzzle` | https://github.com/foss42/apidash/issues/143 | From 91a58a8d316477a380ace257e2ea1db9880d09b2 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 31 Mar 2024 20:31:33 +0530 Subject: [PATCH 127/138] fixes --- lib/codegen/codegen.dart | 2 +- lib/codegen/php/curl.dart | 14 +++----------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index 9146efca..8afc539a 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -81,7 +81,7 @@ class Codegen { case CodegenLanguage.phpGuzzle: return PhpGuzzleCodeGen().getCode(rM); case CodegenLanguage.phpCurl: - return PHPcURLCodeGen().getCode(requestModel, defaultUriScheme); + return PHPcURLCodeGen().getCode(rM); } } } diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index 179b2100..0b9fc2f9 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -163,10 +163,7 @@ function build_data_files(\$boundary, \$fields, \$files) """; - String? getCode( - RequestModel requestModel, - String defaultUriScheme, - ) { + String? getCode(RequestModel requestModel) { String uuid = getNewUuid(); uuid = uuid.replaceAll(RegExp(r'-'), ""); @@ -176,13 +173,8 @@ function build_data_files(\$boundary, \$fields, \$files) bool hasQuery = false; bool hasBody = false; - String url = requestModel.url; - if (!url.contains("://") && url.isNotEmpty) { - url = "$defaultUriScheme://$url"; - } - var rec = getValidRequestUri( - url, + requestModel.url, requestModel.enabledRequestParams, ); @@ -207,7 +199,7 @@ function build_data_files(\$boundary, \$fields, \$files) } var templateUri = jj.Template(kTemplateUri); - result += templateUri.render({"uri": url}); + result += templateUri.render({"uri": requestModel.url}); //checking and adding query params if (uri.hasQuery) { From 850ddc72207a63c97c212723d8f5ee888d21468d Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sun, 31 Mar 2024 20:33:32 +0530 Subject: [PATCH 128/138] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6f9bcd25..339a8039 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,7 @@ API Dash currently supports API integration code generation for the following la | Java | `HttpClient` | | | Java | `okhttp3` | | | Julia | `HTTP` | | +| PHP | `curl` | https://github.com/foss42/apidash/issues/375 | | PHP | `guzzle` | https://github.com/foss42/apidash/issues/143 | We welcome contributions to support other programming languages/libraries/frameworks. Please check out more details [here](https://github.com/foss42/apidash/discussions/80). From 8f89de8fc10e8979fe0893edc8788233e5dc559c Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Mon, 1 Apr 2024 09:16:04 +0530 Subject: [PATCH 129/138] Update editor_request.dart --- lib/screens/home_page/editor_pane/editor_request.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/screens/home_page/editor_pane/editor_request.dart b/lib/screens/home_page/editor_pane/editor_request.dart index 90a60349..ce264454 100644 --- a/lib/screens/home_page/editor_pane/editor_request.dart +++ b/lib/screens/home_page/editor_pane/editor_request.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:apidash/providers/collection_providers.dart'; +import 'package:apidash/providers/providers.dart'; import 'package:apidash/consts.dart'; import 'details_card/details_card.dart'; import 'url_card.dart'; From ad480ecadd9430b95d0f920e002a1f9dd61cb5c8 Mon Sep 17 00:00:00 2001 From: Tilakraj-B Date: Wed, 3 Apr 2024 00:40:38 +0530 Subject: [PATCH 130/138] solved the post request issue. --- lib/codegen/csharp/rest_sharp.dart | 14 +++++--- .../csharp_rest_sharp_codgen_test.dart | 36 ++++++++++--------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/lib/codegen/csharp/rest_sharp.dart b/lib/codegen/csharp/rest_sharp.dart index 4d53e685..ebf70787 100644 --- a/lib/codegen/csharp/rest_sharp.dart +++ b/lib/codegen/csharp/rest_sharp.dart @@ -40,18 +40,21 @@ class Program """; String kTemplateFormData = """ {% if type == "text" -%} - request.AddParameter("{{name}}", "{{value}}", ParameterType.RequestBody); + request.AddParameter("{{name}}", "{{value}}", ParameterType.GetOrPost); {% else -%} request.AddFile("{{name}}", "{{value}}"); {% endif -%} +"""; + String kStringFormDataOption = """ + request.AlwaysMultipartFormData = true; """; String kTemplateJsonData = """ var jsonBody = new {{jsonData}}; request.AddJsonBody(jsonBody); """; String kTemplateTextData = """ - var textBody = "{{textData}}"; - request.AddStringBody(textBody); + var textBody = {{textData}}; + request.AddStringBody(textBody, ContentType.Plain); """; String kStringEnd = """ @@ -144,6 +147,7 @@ class Program "type": data["type"] }); } + result += kStringFormDataOption; result += formDataResult.substring(0, formDataResult.length - 1); result += kStringLineBreak; } @@ -167,8 +171,8 @@ class Program if (requestModel.hasTextData) { jj.Template templateTextData = jj.Template(kTemplateTextData); - result += - templateTextData.render({"textData": requestModel.requestBody}); + result += templateTextData + .render({"textData": jsonEncode(requestModel.requestBody)}); result += kStringLineBreak; } diff --git a/test/codegen/csharp_rest_sharp_codgen_test.dart b/test/codegen/csharp_rest_sharp_codgen_test.dart index 852ef906..52fad758 100644 --- a/test/codegen/csharp_rest_sharp_codgen_test.dart +++ b/test/codegen/csharp_rest_sharp_codgen_test.dart @@ -497,10 +497,8 @@ class Program request.AddHeader("Content-Type", "text/plain"); - var textBody = "{ -"text": "I LOVE Flutter" -}"; - request.AddStringBody(textBody); + var textBody = "{\n\"text\": \"I LOVE Flutter\"\n}"; + request.AddStringBody(textBody, ContentType.Plain); var response = await client.ExecuteAsync(request); Console.WriteLine("Status Code: " + (int)response.StatusCode); @@ -614,9 +612,10 @@ class Program request.AddHeader("Content-Type", "multipart/form-data"); - request.AddParameter("text", "API", ParameterType.RequestBody); - request.AddParameter("sep", "|", ParameterType.RequestBody); - request.AddParameter("times", "3", ParameterType.RequestBody); + request.AlwaysMultipartFormData = true; + request.AddParameter("text", "API", ParameterType.GetOrPost); + request.AddParameter("sep", "|", ParameterType.GetOrPost); + request.AddParameter("times", "3", ParameterType.GetOrPost); var response = await client.ExecuteAsync(request); Console.WriteLine("Status Code: " + (int)response.StatusCode); @@ -651,9 +650,10 @@ class Program request.AddHeader("Content-Type", "multipart/form-data"); request.AddHeader("User-Agent", "Test Agent"); - request.AddParameter("text", "API", ParameterType.RequestBody); - request.AddParameter("sep", "|", ParameterType.RequestBody); - request.AddParameter("times", "3", ParameterType.RequestBody); + request.AlwaysMultipartFormData = true; + request.AddParameter("text", "API", ParameterType.GetOrPost); + request.AddParameter("sep", "|", ParameterType.GetOrPost); + request.AddParameter("times", "3", ParameterType.GetOrPost); var response = await client.ExecuteAsync(request); Console.WriteLine("Status Code: " + (int)response.StatusCode); @@ -687,7 +687,8 @@ class Program request.AddHeader("Content-Type", "multipart/form-data"); - request.AddParameter("token", "xyz", ParameterType.RequestBody); + request.AlwaysMultipartFormData = true; + request.AddParameter("token", "xyz", ParameterType.GetOrPost); request.AddFile("imfile", "/Documents/up/1.png"); var response = await client.ExecuteAsync(request); @@ -722,7 +723,8 @@ class Program request.AddHeader("Content-Type", "multipart/form-data"); - request.AddParameter("token", "xyz", ParameterType.RequestBody); + request.AlwaysMultipartFormData = true; + request.AddParameter("token", "xyz", ParameterType.GetOrPost); request.AddFile("imfile", "/Documents/up/1.png"); var response = await client.ExecuteAsync(request); @@ -760,9 +762,10 @@ class Program request.AddHeader("Content-Type", "multipart/form-data"); - request.AddParameter("text", "API", ParameterType.RequestBody); - request.AddParameter("sep", "|", ParameterType.RequestBody); - request.AddParameter("times", "3", ParameterType.RequestBody); + request.AlwaysMultipartFormData = true; + request.AddParameter("text", "API", ParameterType.GetOrPost); + request.AddParameter("sep", "|", ParameterType.GetOrPost); + request.AddParameter("times", "3", ParameterType.GetOrPost); var response = await client.ExecuteAsync(request); Console.WriteLine("Status Code: " + (int)response.StatusCode); @@ -801,7 +804,8 @@ class Program request.AddHeader("User-Agent", "Test Agent"); request.AddHeader("Keep-Alive", "true"); - request.AddParameter("token", "xyz", ParameterType.RequestBody); + request.AlwaysMultipartFormData = true; + request.AddParameter("token", "xyz", ParameterType.GetOrPost); request.AddFile("imfile", "/Documents/up/1.png"); var response = await client.ExecuteAsync(request); From 81c86614f84de5b8b4d9c342c6a121c097a7ed07 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Thu, 4 Apr 2024 08:36:36 +0530 Subject: [PATCH 131/138] Update consts.dart --- lib/consts.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/consts.dart b/lib/consts.dart index ab174517..a7607dfc 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -272,7 +272,7 @@ const kDefaultContentType = ContentType.json; enum CodegenLanguage { curl("cURL", "bash", "curl"), har("HAR", "json", "har"), - cSharpRestSharp("C# (Rest Sharp)", "cs", "cs"); + cSharpRestSharp("C# (Rest Sharp)", "cs", "cs"), dartHttp("Dart (http)", "dart", "dart"), dartDio("Dart (dio)", "dart", "dart"), goHttp("Go (http)", "go", "go"), From d221809ee6ca21f6dede5e933fa0706c1e153fdf Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Fri, 5 Apr 2024 00:51:45 +0530 Subject: [PATCH 132/138] Add String extensions --- lib/extensions/extensions.dart | 1 + lib/extensions/string_extensions.dart | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 lib/extensions/extensions.dart create mode 100644 lib/extensions/string_extensions.dart diff --git a/lib/extensions/extensions.dart b/lib/extensions/extensions.dart new file mode 100644 index 00000000..d8c9fa84 --- /dev/null +++ b/lib/extensions/extensions.dart @@ -0,0 +1 @@ +export 'string_extensions.dart'; diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart new file mode 100644 index 00000000..5d929489 --- /dev/null +++ b/lib/extensions/string_extensions.dart @@ -0,0 +1,5 @@ +extension StringExtension on String { + String capitalize() { + return "${this[0].toUpperCase()}${substring(1).toLowerCase()}"; + } +} From 7952ca849d7e1375e259c03dfe9539430d4e0212 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Fri, 5 Apr 2024 00:52:01 +0530 Subject: [PATCH 133/138] Update c# --- lib/codegen/csharp/rest_sharp.dart | 222 +++++++++--------- .../csharp_rest_sharp_codgen_test.dart | 70 +++--- 2 files changed, 153 insertions(+), 139 deletions(-) diff --git a/lib/codegen/csharp/rest_sharp.dart b/lib/codegen/csharp/rest_sharp.dart index ebf70787..d3c69193 100644 --- a/lib/codegen/csharp/rest_sharp.dart +++ b/lib/codegen/csharp/rest_sharp.dart @@ -1,19 +1,18 @@ import 'dart:convert'; +import 'package:apidash/consts.dart'; import 'package:jinja/jinja.dart' as jj; import '../../models/request_model.dart'; -import '../../utils/har_utils.dart'; +import '../../extensions/extensions.dart'; import '../../utils/http_utils.dart'; class CSharpRestSharp { - String kStringLineBreak = """ - - -"""; String kStringImports = """ using System; using RestSharp; using System.Threading.Tasks; + + """; String kStringInit = """ @@ -26,35 +25,57 @@ class Program String kInitClientTemplate = """ const String _baseUrl = "{{baseUrl}}"; var client = new RestClient(_baseUrl); + + """; String kMethodTypeTemplate = """ var request = new RestRequest("{{path}}", Method.{{method}}); + + """; String kTemplateParams = """ request.AddQueryParameter("{{param}}", "{{value}}"); + """; + String kTemplateHeaders = """ request.AddHeader("{{header}}", "{{value}}"); + """; + String kTemplateFormData = """ {% if type == "text" -%} request.AddParameter("{{name}}", "{{value}}", ParameterType.GetOrPost); {% else -%} - request.AddFile("{{name}}", "{{value}}"); + request.AddFile("{{name}}", "{{value}}", options: options); {% endif -%} """; + String kStringFormDataOption = """ request.AlwaysMultipartFormData = true; """; + + String kStringFormdataFileOption = """ + var options = new FileParameterOptions + { + DisableFilenameEncoding = true + }; +"""; + String kTemplateJsonData = """ var jsonBody = new {{jsonData}}; request.AddJsonBody(jsonBody); + + """; + String kTemplateTextData = """ var textBody = {{textData}}; request.AddStringBody(textBody, ContentType.Plain); + + """; String kStringEnd = """ @@ -71,112 +92,103 @@ class Program String? getCode(RequestModel requestModel) { try { - var harJson = - requestModelToHARJsonRequest(requestModel, useEnabled: true); - String result = ""; - jj.Template kNodejsImportTemplate = jj.Template(kStringImports); - String importsData = kNodejsImportTemplate.render(); - result += importsData; - result += kStringLineBreak; + var rec = getValidRequestUri( + requestModel.url, + requestModel.enabledRequestParams, + ); + Uri? uri = rec.$1; + if (uri != null) { + jj.Template kNodejsImportTemplate = jj.Template(kStringImports); + String importsData = kNodejsImportTemplate.render(); + result += importsData; - result += kStringInit; + result += kStringInit; - Uri uri = - getValidRequestUri(requestModel.url, requestModel.requestParams).$1!; - var baseUrl = - "${uri.scheme}://${uri.host}${uri.hasPort ? ":${uri.port}" : ""}${uri.hasFragment ? "#${uri.fragment}" : ""}"; + jj.Template templateInitClient = jj.Template(kInitClientTemplate); + String initClient = templateInitClient + .render({"baseUrl": "${uri.scheme}://${uri.authority}"}); + result += initClient; - jj.Template templateInitClient = jj.Template(kInitClientTemplate); - String initClient = templateInitClient.render({"baseUrl": baseUrl}); - result += initClient; - result += kStringLineBreak; - - jj.Template templateMethodType = jj.Template(kMethodTypeTemplate); - String methodType = templateMethodType.render({ - "path": uri.path, - "method": requestModel.method.name.replaceRange( - 0, - 1, - requestModel.method.name[0] - .toUpperCase()) // making the first character capital - }); - result += methodType; - result += kStringLineBreak; - - var params = harJson["queryString"]; - if (params.isNotEmpty) { - jj.Template templateParams = jj.Template(kTemplateParams); - String paramsResult = ""; - for (var query in params) { - paramsResult += templateParams - .render({"param": query["name"], "value": query["value"]}); - paramsResult += "\n"; - } - result += paramsResult.substring(0, paramsResult.length - 1); - result += kStringLineBreak; - } - - var headers = harJson["headers"]; - if (headers.isNotEmpty) { - jj.Template templateHeaders = jj.Template(kTemplateHeaders); - String headersResult = ""; - for (var header in headers) { - headersResult += templateHeaders.render({ - "header": header["name"], - "value": header["name"] == "Content-Type" - ? header["value"] - .toString() - .split(';') - .first // boundary is removed - : header["value"] - }); - headersResult += '\n'; - } - result += headersResult.substring(0, headersResult.length - 1); - result += kStringLineBreak; - } - - if (requestModel.hasFormData) { - jj.Template templateFormData = jj.Template(kTemplateFormData); - String formDataResult = ""; - for (var data in requestModel.formDataMapList) { - formDataResult += templateFormData.render({ - "name": data["name"], - "value": data["value"], - "type": data["type"] - }); - } - result += kStringFormDataOption; - result += formDataResult.substring(0, formDataResult.length - 1); - result += kStringLineBreak; - } - - if (requestModel.hasJsonData) { - var templateJsonData = jj.Template(kTemplateJsonData); - Map bodyData = json.decode(requestModel.requestBody!); - String jsonDataResult = "{\n"; - - bodyData.forEach((key, value) { - jsonDataResult += "\t\t\t\t\t$key = \"$value\",\n"; + jj.Template templateMethodType = jj.Template(kMethodTypeTemplate); + String methodType = templateMethodType.render({ + "path": uri.path, + "method": requestModel.method.name.capitalize(), }); - jsonDataResult = jsonDataResult.length >= 3 - ? jsonDataResult.substring(0, jsonDataResult.length - 2) - : jsonDataResult; - jsonDataResult += "\n\t\t\t\t\t}"; + result += methodType; - result += templateJsonData.render({"jsonData": jsonDataResult}); - result += kStringLineBreak; + if (uri.hasQuery) { + var params = uri.queryParameters; + if (params.isNotEmpty) { + jj.Template templateParams = jj.Template(kTemplateParams); + String paramsResult = ""; + for (var item in params.entries) { + paramsResult += templateParams + .render({"param": item.key, "value": item.value}); + } + result += "$paramsResult\n"; + } + } + + var headersList = requestModel.enabledRequestHeaders; + if (headersList != null || + requestModel.hasJsonData || + requestModel.hasTextData) { + var headers = requestModel.enabledHeadersMap; + if (requestModel.hasJsonData || requestModel.hasTextData) { + headers[kHeaderContentType] = + requestModel.requestBodyContentType.header; + } + if (headers.isNotEmpty) { + jj.Template templateHeaders = jj.Template(kTemplateHeaders); + String headersResult = ""; + for (var item in headers.entries) { + headersResult += templateHeaders + .render({"header": item.key, "value": item.value}); + } + result += "$headersResult\n"; + } + } + + if (requestModel.hasFormData) { + jj.Template templateFormData = jj.Template(kTemplateFormData); + String formDataResult = ""; + for (var data in requestModel.formDataMapList) { + formDataResult += templateFormData.render({ + "name": data["name"], + "value": data["value"], + "type": data["type"] + }); + } + result += kStringFormDataOption; + if (requestModel.hasFileInFormData) { + result += kStringFormdataFileOption; + } + result += "$formDataResult\n"; + } + + if (requestModel.hasJsonData) { + var templateJsonData = jj.Template(kTemplateJsonData); + Map bodyData = + json.decode(requestModel.requestBody!); + List jsonArr = []; + + bodyData.forEach((key, value) { + jsonArr += ["$key = \"$value\""]; + }); + String jsonDataResult = "{\n${jsonArr.join(",\n")}\n}"; + + result += templateJsonData.render({"jsonData": jsonDataResult}); + } + + if (requestModel.hasTextData) { + jj.Template templateTextData = jj.Template(kTemplateTextData); + result += templateTextData + .render({"textData": jsonEncode(requestModel.requestBody)}); + } + + result += kStringEnd; } - - if (requestModel.hasTextData) { - jj.Template templateTextData = jj.Template(kTemplateTextData); - result += templateTextData - .render({"textData": jsonEncode(requestModel.requestBody)}); - result += kStringLineBreak; - } - - result += kStringEnd; return result; } catch (e) { return null; diff --git a/test/codegen/csharp_rest_sharp_codgen_test.dart b/test/codegen/csharp_rest_sharp_codgen_test.dart index 52fad758..7f35beeb 100644 --- a/test/codegen/csharp_rest_sharp_codgen_test.dart +++ b/test/codegen/csharp_rest_sharp_codgen_test.dart @@ -457,7 +457,7 @@ class Program { static async Task Main(){ try{ - const String _baseUrl = "https://api.apidash.dev"; + const String _baseUrl = "http://api.apidash.dev"; var client = new RestClient(_baseUrl); var request = new RestRequest("", Method.Head); @@ -474,7 +474,7 @@ class Program """; expect( codegen.getCode( - CodegenLanguage.cSharpRestSharp, requestModelHead2, "https"), + CodegenLanguage.cSharpRestSharp, requestModelHead2, "http"), expectedCode); }); }); @@ -533,13 +533,13 @@ class Program request.AddHeader("Content-Type", "application/json"); var jsonBody = new { -\t\t\t\t\ttext = "I LOVE Flutter", -\t\t\t\t\tflag = "null", -\t\t\t\t\tmale = "true", -\t\t\t\t\tfemale = "false", -\t\t\t\t\tno = "1.2", -\t\t\t\t\tarr = "[null, true, false, null]" -\t\t\t\t\t}; +text = "I LOVE Flutter", +flag = "null", +male = "true", +female = "false", +no = "1.2", +arr = "[null, true, false, null]" +}; request.AddJsonBody(jsonBody); var response = await client.ExecuteAsync(request); @@ -572,12 +572,12 @@ class Program var request = new RestRequest("/case/lower", Method.Post); - request.AddHeader("Content-Type", "application/json"); request.AddHeader("User-Agent", "Test Agent"); + request.AddHeader("Content-Type", "application/json"); var jsonBody = new { -\t\t\t\t\ttext = "I LOVE Flutter" -\t\t\t\t\t}; +text = "I LOVE Flutter" +}; request.AddJsonBody(jsonBody); var response = await client.ExecuteAsync(request); @@ -610,8 +610,6 @@ class Program var request = new RestRequest("/io/form", Method.Post); - request.AddHeader("Content-Type", "multipart/form-data"); - request.AlwaysMultipartFormData = true; request.AddParameter("text", "API", ParameterType.GetOrPost); request.AddParameter("sep", "|", ParameterType.GetOrPost); @@ -647,7 +645,6 @@ class Program var request = new RestRequest("/io/form", Method.Post); - request.AddHeader("Content-Type", "multipart/form-data"); request.AddHeader("User-Agent", "Test Agent"); request.AlwaysMultipartFormData = true; @@ -685,11 +682,13 @@ class Program var request = new RestRequest("/io/img", Method.Post); - request.AddHeader("Content-Type", "multipart/form-data"); - request.AlwaysMultipartFormData = true; + var options = new FileParameterOptions + { + DisableFilenameEncoding = true + }; request.AddParameter("token", "xyz", ParameterType.GetOrPost); - request.AddFile("imfile", "/Documents/up/1.png"); + request.AddFile("imfile", "/Documents/up/1.png", options: options); var response = await client.ExecuteAsync(request); Console.WriteLine("Status Code: " + (int)response.StatusCode); @@ -721,11 +720,13 @@ class Program var request = new RestRequest("/io/img", Method.Post); - request.AddHeader("Content-Type", "multipart/form-data"); - request.AlwaysMultipartFormData = true; + var options = new FileParameterOptions + { + DisableFilenameEncoding = true + }; request.AddParameter("token", "xyz", ParameterType.GetOrPost); - request.AddFile("imfile", "/Documents/up/1.png"); + request.AddFile("imfile", "/Documents/up/1.png", options: options); var response = await client.ExecuteAsync(request); Console.WriteLine("Status Code: " + (int)response.StatusCode); @@ -760,8 +761,6 @@ class Program request.AddQueryParameter("size", "2"); request.AddQueryParameter("len", "3"); - request.AddHeader("Content-Type", "multipart/form-data"); - request.AlwaysMultipartFormData = true; request.AddParameter("text", "API", ParameterType.GetOrPost); request.AddParameter("sep", "|", ParameterType.GetOrPost); @@ -800,13 +799,16 @@ class Program request.AddQueryParameter("size", "2"); request.AddQueryParameter("len", "3"); - request.AddHeader("Content-Type", "multipart/form-data"); request.AddHeader("User-Agent", "Test Agent"); request.AddHeader("Keep-Alive", "true"); request.AlwaysMultipartFormData = true; + var options = new FileParameterOptions + { + DisableFilenameEncoding = true + }; request.AddParameter("token", "xyz", ParameterType.GetOrPost); - request.AddFile("imfile", "/Documents/up/1.png"); + request.AddFile("imfile", "/Documents/up/1.png", options: options); var response = await client.ExecuteAsync(request); Console.WriteLine("Status Code: " + (int)response.StatusCode); @@ -844,9 +846,9 @@ class Program request.AddHeader("Content-Type", "application/json"); var jsonBody = new { -\t\t\t\t\tname = "morpheus", -\t\t\t\t\tjob = "zion resident" -\t\t\t\t\t}; +name = "morpheus", +job = "zion resident" +}; request.AddJsonBody(jsonBody); var response = await client.ExecuteAsync(request); @@ -885,9 +887,9 @@ class Program request.AddHeader("Content-Type", "application/json"); var jsonBody = new { -\t\t\t\t\tname = "marfeus", -\t\t\t\t\tjob = "accountant" -\t\t\t\t\t}; +name = "marfeus", +job = "accountant" +}; request.AddJsonBody(jsonBody); var response = await client.ExecuteAsync(request); @@ -956,9 +958,9 @@ class Program request.AddHeader("Content-Type", "application/json"); var jsonBody = new { -\t\t\t\t\tname = "marfeus", -\t\t\t\t\tjob = "accountant" -\t\t\t\t\t}; +name = "marfeus", +job = "accountant" +}; request.AddJsonBody(jsonBody); var response = await client.ExecuteAsync(request); From e7356e4154f041b238181650c05f9d7b329d0196 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Fri, 5 Apr 2024 00:55:06 +0530 Subject: [PATCH 134/138] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 339a8039..b73ec29d 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,7 @@ API Dash currently supports API integration code generation for the following la | ---------------------- | ------------- | ------- | | cURL | | | | HAR | | | +| C# | `RestSharp` | | | Dart | `http` | | | Dart | `dio` | | | Go | `net/http` | | From a4572b39116ef8999a61a8844cb3a8938c3a7b3f Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Fri, 5 Apr 2024 01:26:32 +0530 Subject: [PATCH 135/138] Update curl.dart --- lib/codegen/php/curl.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index 0b9fc2f9..4d0ac5e9 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -169,7 +169,6 @@ function build_data_files(\$boundary, \$fields, \$files) try { String result = ""; - bool hasHeaders = false; bool hasQuery = false; bool hasBody = false; From bc532ae5933f7b38c2cf7d34ec62966010628ac9 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sat, 6 Apr 2024 13:30:24 +0530 Subject: [PATCH 136/138] remove boundary --- lib/codegen/codegen.dart | 2 +- lib/codegen/ruby/faraday.dart | 61 ++++++++++++++++------------------- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/lib/codegen/codegen.dart b/lib/codegen/codegen.dart index 90fea8fa..b293d67f 100644 --- a/lib/codegen/codegen.dart +++ b/lib/codegen/codegen.dart @@ -74,7 +74,7 @@ class Codegen { case CodegenLanguage.pythonRequests: return PythonRequestsCodeGen().getCode(rM, boundary: boundary); case CodegenLanguage.rubyFaraday: - return RubyFaradayCodeGen().getCode(rM, boundary: boundary ?? getNewUuid()); + return RubyFaradayCodeGen().getCode(rM); case CodegenLanguage.rustActix: return RustActixCodeGen().getCode(rM, boundary: boundary); case CodegenLanguage.rustCurl: diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index 04c166f0..852f0dfb 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -21,20 +21,27 @@ require 'faraday/multipart' '''; final String kTemplateRequestUrl = """ -\nREQUEST_URL = URI("{{ url }}")\n\n + +REQUEST_URL = URI("{{ url }}") + + """; final String kTemplateBody = """ -PAYLOAD = <<-{{ boundary }} +PAYLOAD = < Faraday::Multipart::ParamPart.new("{{ param.value }}", "text/plain"), {% elif param.type == "file" %} "{{ param.name }}" => Faraday::Multipart::FilePart.new("{{ param.value }}", "application/octet-stream"),{% endif %}{% endfor %} -}\n\n +} + + """; final String kTemplateFormParamsWithoutFile = """ @@ -44,23 +51,26 @@ PAYLOAD = URI.encode_www_form({\n{% for param in params %} "{{ param.name }}" = final String kTemplateConnection = """ conn = Faraday.new do |faraday| faraday.adapter Faraday.default_adapter{% if hasFile %}\n faraday.request :multipart{% endif %} -end\n\n +end + + """; final String kTemplateRequestStart = """ -response = conn.{{ method|lower }}(REQUEST_URL{% if doesMethodAcceptBody and containsBody %}, PAYLOAD{% endif %}) do |req|\n -"""; +response = conn.{{ method|lower }}(REQUEST_URL{% if doesMethodAcceptBody and containsBody %}, PAYLOAD{% endif %}) do |req| - final String kTemplateRequestOptionsBoundary = """ - req.options.boundary = "{{ boundary }}"\n """; final String kTemplateRequestParams = """ - req.params = {\n{% for key, val in params %} "{{ key }}" => "{{ val }}",\n{% endfor %} }\n + req.params = { +{% for key, val in params %} "{{ key }}" => "{{ val }}",\n{% endfor %} } + """; final String kTemplateRequestHeaders = """ - req.headers = {\n{% for key, val in headers %} "{{ key }}" => "{{ val }}",\n{% endfor %} }\n + req.headers = { +{% for key, val in headers %} "{{ key }}" => "{{ val }}",\n{% endfor %} } + """; final String kStringDeleteRequestBody = """ @@ -68,7 +78,8 @@ response = conn.{{ method|lower }}(REQUEST_URL{% if doesMethodAcceptBody and con """; final String kStringRequestEnd = """ -end\n +end + """; final String kStringResponse = """ @@ -77,18 +88,11 @@ puts "Response Body: #{response.body}" """; String? getCode( - RequestModel requestModel, { - String? boundary, - }) { + RequestModel requestModel, + ) { try { String result = ""; - if (boundary != null) { - // boundary needs to start with a character, hence we append apidash - // and remove hyphen characters from the existing boundary - boundary = "apidash_${boundary.replaceAll(RegExp("-"), "")}"; - } - var rec = getValidRequestUri( requestModel.url, requestModel.enabledRequestParams, @@ -121,8 +125,7 @@ puts "Response Body: #{response.body}" } else if (requestModel.hasJsonData || requestModel.hasTextData) { var templateBody = jj.Template(kTemplateBody); result += templateBody.render({ - "body": requestModel.requestBody, // - "boundary": boundary, + "body": requestModel.requestBody, }); } @@ -135,24 +138,16 @@ puts "Response Body: #{response.body}" // start of the request sending var templateRequestStart = jj.Template(kTemplateRequestStart); result += templateRequestStart.render({ - "method": requestModel.method.name, // + "method": requestModel.method.name, "doesMethodAcceptBody": kMethodsWithBody.contains(requestModel.method) && requestModel.method != HTTPVerb.delete, // - "containsBody": requestModel.hasBody, // + "containsBody": requestModel.hasBody, }); - if (requestModel.hasFormDataContentType && requestModel.hasFileInFormData) { - var templateRequestOptionsBoundary = jj.Template(kTemplateRequestOptionsBoundary); - result += templateRequestOptionsBoundary.render({"boundary": boundary}); - } - var headers = requestModel.enabledHeadersMap; if (requestModel.hasBody && !requestModel.hasContentTypeHeader) { if (requestModel.hasJsonData || requestModel.hasTextData) { headers["Content-Type"] = requestModel.requestBodyContentType.header; - } else if (requestModel.hasFormData) { - headers["Content-Type"] = - (requestModel.hasFileInFormData) ? "multipart/form-data" : "application/x-www-form-urlencoded"; } } From 2c6b23cb751546b144f8e9d8b03e4bd598c1f1f6 Mon Sep 17 00:00:00 2001 From: Ankit Mahato Date: Sat, 6 Apr 2024 13:32:03 +0530 Subject: [PATCH 137/138] Update ruby_faraday_codegen_test.dart --- test/codegen/ruby_faraday_codegen_test.dart | 72 +++++++-------------- 1 file changed, 23 insertions(+), 49 deletions(-) diff --git a/test/codegen/ruby_faraday_codegen_test.dart b/test/codegen/ruby_faraday_codegen_test.dart index 5f94080c..c3d8fe52 100644 --- a/test/codegen/ruby_faraday_codegen_test.dart +++ b/test/codegen/ruby_faraday_codegen_test.dart @@ -331,11 +331,11 @@ require 'faraday' REQUEST_URL = URI("https://api.apidash.dev/case/lower") -PAYLOAD = <<-apidash_a5d7a5d09d721f398905c39274c7fa33 +PAYLOAD = < "application/x-www-form-urlencoded", - } end puts "Status Code: #{response.status}" @@ -476,14 +470,13 @@ end response = conn.post(REQUEST_URL, PAYLOAD) do |req| req.headers = { "User-Agent" => "Test Agent", - "Content-Type" => "application/x-www-form-urlencoded", } end puts "Status Code: #{response.status}" puts "Response Body: #{response.body}" """; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost5, "https", boundary: "test"), expectedCode); + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost5, "https"), expectedCode); }); test('POST 6', () { const expectedCode = r"""require 'uri' @@ -503,18 +496,13 @@ conn = Faraday.new do |faraday| end response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.options.boundary = "apidash_6f6629609fb41f398905c39274c7fa33" - req.headers = { - "Content-Type" => "multipart/form-data", - } end puts "Status Code: #{response.status}" puts "Response Body: #{response.body}" """; expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost6, "https", - boundary: "6f6629609fb41f398905c39274c7fa33"), + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost6, "https"), expectedCode); }); test('POST 7', () { @@ -535,18 +523,13 @@ conn = Faraday.new do |faraday| end response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.options.boundary = "apidash_3955fcc0a0b71f398905c39274c7fa33" - req.headers = { - "Content-Type" => "multipart/form-data", - } end puts "Status Code: #{response.status}" puts "Response Body: #{response.body}" """; expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost7, "https", - boundary: "3955fcc0a0b71f398905c39274c7fa33"), + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost7, "https"), expectedCode); }); test('POST 8', () { @@ -566,9 +549,6 @@ conn = Faraday.new do |faraday| end response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.headers = { - "Content-Type" => "application/x-www-form-urlencoded", - } req.params = { "size" => "2", "len" => "3", @@ -578,7 +558,7 @@ end puts "Status Code: #{response.status}" puts "Response Body: #{response.body}" """; - expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost8, "https", boundary: "test"), expectedCode); + expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost8, "https"), expectedCode); }); test('POST 9', () { const expectedCode = r"""require 'uri' @@ -598,11 +578,9 @@ conn = Faraday.new do |faraday| end response = conn.post(REQUEST_URL, PAYLOAD) do |req| - req.options.boundary = "apidash_599e5a20a1361f398905c39274c7fa33" req.headers = { "User-Agent" => "Test Agent", "Keep-Alive" => "true", - "Content-Type" => "multipart/form-data", } req.params = { "size" => "2", @@ -614,8 +592,7 @@ puts "Status Code: #{response.status}" puts "Response Body: #{response.body}" """; expect( - codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost9, "https", - boundary: "599e5a20a1361f398905c39274c7fa33"), + codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost9, "https"), expectedCode); }); }); @@ -627,12 +604,12 @@ require 'faraday' REQUEST_URL = URI("https://reqres.in/api/users/2") -PAYLOAD = <<-apidash_b4e90990a34b1f398905c39274c7fa33 +PAYLOAD = < Date: Sat, 6 Apr 2024 13:42:35 +0530 Subject: [PATCH 138/138] cleanup ContentType --- lib/codegen/java/async_http_client.dart | 4 ++-- lib/codegen/js/axios.dart | 2 +- lib/codegen/js/fetch.dart | 2 +- lib/codegen/php/curl.dart | 4 ++-- lib/codegen/php/guzzle.dart | 2 +- lib/codegen/ruby/faraday.dart | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/codegen/java/async_http_client.dart b/lib/codegen/java/async_http_client.dart index ec804cc1..86fdf553 100644 --- a/lib/codegen/java/async_http_client.dart +++ b/lib/codegen/java/async_http_client.dart @@ -148,9 +148,9 @@ public class Main { // especially sets up Content-Type header if the request has a body // and Content-Type is not explicitely set by the developer if (hasBody && - !requestModel.enabledHeadersMap.containsKey('Content-Type')) { + !requestModel.enabledHeadersMap.containsKey(kHeaderContentType)) { result += templateRequestHeader - .render({"name": 'Content-Type', "value": contentType}); + .render({"name": kHeaderContentType, "value": contentType}); } // setting up rest of the request headers diff --git a/lib/codegen/js/axios.dart b/lib/codegen/js/axios.dart index 301ecf46..00d4d1a9 100644 --- a/lib/codegen/js/axios.dart +++ b/lib/codegen/js/axios.dart @@ -90,7 +90,7 @@ axios(config) m[i["name"]] = i["value"]; } if (requestModel.hasFormData) { - m[kHeaderContentType] = 'multipart/form-data'; + m[kHeaderContentType] = ContentType.formdata.header; } result += templateHeader .render({"headers": padMultilineString(kEncoder.convert(m), 2)}); diff --git a/lib/codegen/js/fetch.dart b/lib/codegen/js/fetch.dart index 9b5f8161..cd6732a6 100644 --- a/lib/codegen/js/fetch.dart +++ b/lib/codegen/js/fetch.dart @@ -99,7 +99,7 @@ fetch(url, options) var m = {}; for (var i in headers) { // fetch can automatically add the Content-Type header when FormData is passed as body - if (i["name"] == "Content-Type" && requestModel.hasFormData) { + if (i["name"] == kHeaderContentType && requestModel.hasFormData) { continue; } m[i["name"]] = i["value"]; diff --git a/lib/codegen/php/curl.dart b/lib/codegen/php/curl.dart index 4d0ac5e9..86897383 100644 --- a/lib/codegen/php/curl.dart +++ b/lib/codegen/php/curl.dart @@ -238,8 +238,8 @@ function build_data_files(\$boundary, \$fields, \$files) if (requestModel.hasFormData) { // we will override any existing boundary and use our own boundary - m['Content-Type'] = - "multipart/form-data; boundary=-------------$uuid"; + m[kHeaderContentType] = + "${ContentType.formdata.header}; boundary=-------------$uuid"; var boundaryUniqueIdTemplate = jj.Template(kBoundaryUniqueIdTemplate); diff --git a/lib/codegen/php/guzzle.dart b/lib/codegen/php/guzzle.dart index c0e5562e..c7d498da 100644 --- a/lib/codegen/php/guzzle.dart +++ b/lib/codegen/php/guzzle.dart @@ -107,7 +107,7 @@ echo \$res->getBody(); headersString += "\t\t\t\t'$key' => '$value', \n"; }); if (requestModel.hasFormData) { - m['Content-Type'] = 'multipart/form-data'; + m[kHeaderContentType] = ContentType.formdata.header; } headersString = headersString.substring( 0, headersString.length - 2); // Removing trailing comma and space diff --git a/lib/codegen/ruby/faraday.dart b/lib/codegen/ruby/faraday.dart index 852f0dfb..5023e183 100644 --- a/lib/codegen/ruby/faraday.dart +++ b/lib/codegen/ruby/faraday.dart @@ -147,7 +147,7 @@ puts "Response Body: #{response.body}" var headers = requestModel.enabledHeadersMap; if (requestModel.hasBody && !requestModel.hasContentTypeHeader) { if (requestModel.hasJsonData || requestModel.hasTextData) { - headers["Content-Type"] = requestModel.requestBodyContentType.header; + headers[kHeaderContentType] = requestModel.requestBodyContentType.header; } }