diff --git a/.gitignore b/.gitignore index a4df65b9..9268964a 100644 --- a/.gitignore +++ b/.gitignore @@ -49,8 +49,10 @@ linux/ macos/ windows/ web/ +ios/ .vscode/* icons/ coverage/* installers/* .metadata +.fvm/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 32c82a67..140188ac 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,10 +4,10 @@ We value your participation in this open source project. This page will give you You can contribute to the project in any or all of the following ways: -- [Ask a question](https://github.com/foss42/api-dash/discussions) -- [Submit a bug report](https://github.com/foss42/api-dash/issues/new/choose) -- [Request a new feature](https://github.com/foss42/api-dash/issues/new/choose) -- [Suggest ways to improve the developer experience of an existing feature](https://github.com/foss42/api-dash/issues/new/choose) +- [Ask a question](https://github.com/foss42/apidash/discussions) +- [Submit a bug report](https://github.com/foss42/apidash/issues/new/choose) +- [Request a new feature](https://github.com/foss42/apidash/issues/new/choose) +- [Suggest ways to improve the developer experience of an existing feature](https://github.com/foss42/apidash/issues/new/choose) - Add documentation - Add a new feature, resolve an existing issue or add a new test to the project. (Goto [Code Contribution Guidelines](#code-contribution-guidelines)). @@ -27,11 +27,11 @@ We currently do not accept PRs that involve: ### Resolving an existing issue / Adding a requested feature -You can find all existing issues [here](https://github.com/foss42/api-dash/issues). A good place to start is to take a look at ["good first issues"](https://github.com/foss42/api-dash/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). +You can find all existing issues [here](https://github.com/foss42/apidash/issues). A good place to start is to take a look at ["good first issues"](https://github.com/foss42/apidash/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). **Step 1** - Identify the issue you want to work on. **Step 2** - Comment on the issue so that we can discuss how to approach and solve the problem. -**Step 3** - Fork the [`foss42/api-dash`](https://github.com/foss42/api-dash) repo to your account. +**Step 3** - Fork the [`foss42/apidash`](https://github.com/foss42/apidash) repo to your account. **Step 4** - Create a new branch in your fork and name it `add-feature-xyz` or `resolve-issue-xyz`. **Step 5** - Run API Dash locally (More details [here](#how-to-run-api-dash-locally)). **Step 6** - Make code changes in the branch. @@ -41,8 +41,8 @@ You can find all existing issues [here](https://github.com/foss42/api-dash/issue ### Adding a new feature -**Step 1** - Open an [issue](https://github.com/foss42/api-dash/issues/new/choose) so that we can discuss on the new feature. -**Step 2** - Fork the [`foss42/api-dash`](https://github.com/foss42/api-dash) repo to your account. +**Step 1** - Open an [issue](https://github.com/foss42/apidash/issues/new/choose) so that we can discuss on the new feature. +**Step 2** - Fork the [`foss42/apidash`](https://github.com/foss42/apidash) repo to your account. **Step 3** - Create a new branch in your fork and name it `add-feature-xyz`. **Step 4** - Run API Dash locally (More details [here](#how-to-run-api-dash-locally)). **Step 5** - Make the necessary code changes required to implement the feature in the branch. @@ -61,7 +61,7 @@ You can contribute by adding missing/new tests for: - Services (`lib/services/`). **Step 1** - Identify the test you want to add or improve. -**Step 2** - Fork the [`foss42/api-dash`](https://github.com/foss42/api-dash) repo to your account. +**Step 2** - Fork the [`foss42/apidash`](https://github.com/foss42/apidash) repo to your account. **Step 3** - Create a new branch in your fork and name it `add-test-xyz`. **Step 4** - Add the test to an existing test file or create a new test file in the `test` folder. **Step 5** - Run the tests locally (More details [here](#how-to-run-tests)). @@ -72,50 +72,11 @@ You can contribute by adding missing/new tests for: ### What is the supported Flutter/Dart version? -As the project has not migrated to Dart 3, the latest Flutter version we support is `3.7.12` (Dart `2.19.6`). If you are using newer flutter version, you will get errors. +This project supports the latest Dart 3 & Flutter version. If you are using older Flutter version that does not support Dart 3, you might get errors. -In case you are setting up Flutter for the first time, just go ahead and download version `3.7.12` (Stable) SDK from the [Flutter SDK Archive](https://docs.flutter.dev/release/archive). Then proceed with the Flutter installation. +In case you are setting up Flutter for the first time, just go ahead and download the latest (Stable) SDK from the [Flutter SDK Archive](https://docs.flutter.dev/release/archive). Then proceed with the Flutter installation. -In case you have already setup Flutter, make sure to switch to `stable` branch and use the instructions below to downgrade/upgrade if you are on any version other than the one mentioned above. - -1. Locate the directory where you have installed Flutter SDK and navigate to it. The contents of the directory should resemble the following: -``` -$ ls -analysis_options.yaml CONTRIBUTING.md flutter_root.iml TESTOWNERS -AUTHORS dartdoc_options.yaml LICENSE version -bin dev packages -CODE_OF_CONDUCT.md examples PATENT_GRANT -CODEOWNERS flutter_console.bat README.md -``` - -2. In the same directory, execute the following command to change the head of the local Flutter SDK to version `3.7.12`. -``` -git checkout 4d9e56e -``` - -3. Run the Flutter Doctor command to verify: -``` -$ flutter doctor -v - -[!] Flutter (Channel unknown, 3.7.12, on Ubuntu 22.04.2 LTS 5.19.0-42-generic, - locale en_IN) - ! Flutter version 3.7.12 on channel unknown at - /home//snap/flutter/common/flutter - Currently on an unknown channel. Run `flutter channel` to switch to an - official channel. - If that doesn't fix the issue, reinstall Flutter by following instructions - at https://flutter.dev/docs/get-started/install. - ! Unknown upstream repository. - Reinstall Flutter by following instructions at - https://flutter.dev/docs/get-started/install. - • Framework revision 4d9e56e694 (5 weeks ago), 2023-04-17 21:47:46 -0400 - • Engine revision 1a65d409c7 - • Dart version 2.19.6 - • DevTools version 2.20.1 - • If those were intentional, you can disregard the above warnings; however - it is recommended to use "git" directly to perform update checks and - upgrades. -``` +In case you have already setup Flutter, make sure to switch to `stable` branch and upgrade it. ### How to run API Dash locally? @@ -125,16 +86,15 @@ $ flutter doctor -v 4. This project uses [Records feature in Dart](https://github.com/dart-lang/language/blob/main/accepted/future-releases/records/records-feature-specification.md), so to run the project execute the following command: ``` -flutter run --enable-experiment=records +flutter run ``` -**Note**: In case you encounter an invalid Dart Package name error on your first run, rename the project's folder name from "api-dash" to "apidash" and re-run. ### How to run tests? To run tests execute the following command: ``` -flutter test --enable-experiment=records --coverage +flutter test --coverage ``` To generate coverage report as html execute: @@ -151,6 +111,20 @@ To view the coverage report in the browser for further analysis, execute: open coverage/html/index.html ``` +#### Testing a single file + +To run tests specified in a single file, execute the following command: + +``` +flutter test .dart +``` + +Example: + +``` +flutter test test/widgets/codegen_previewer_test.dart +``` + ### How to add a new package to pubspec.yaml? Instead of copy pasting from pub.dev, it is recommended that you use `flutter pub add package_name` to add a new package to `pubspec.yaml`. You can read more [here](https://docs.flutter.dev/packages-and-plugins/using-packages#adding-a-package-dependency-to-an-app-using-flutter-pub-add). diff --git a/INSTALLATION.md b/INSTALLATION.md index 496a4009..5bffd9fa 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -1,13 +1,13 @@ # Installation Instructions ## Windows -Download the latest Windows Installer (64 bit) from [here](https://github.com/foss42/api-dash/releases/latest) +Download the latest Windows Installer (64 bit) from [here](https://github.com/foss42/apidash/releases/latest) To install it, simply double click on the installer and follow the step by step installation wizard. ## MacOS -Download the latest MacOS Installer (Universal - Intel and Apple Silicon) from [here](https://github.com/foss42/api-dash/releases/latest) +Download the latest MacOS Installer (Universal - Intel and Apple Silicon) from [here](https://github.com/foss42/apidash/releases/latest) **As this app is distributed outside the App Store you have to follow the following instructions to setup and run it only for the first time.** @@ -46,7 +46,7 @@ Note: The next step has to be performed twice so that macOS adds the app to whit ### Debian-based Linux Distributions (Debian, Ubuntu, Linux Mint, etc.) -Download the `.deb` file from the [latest release](https://github.com/foss42/api-dash/releases/latest) corresponding to you CPU architecture (x64/amd64 or arm64). +Download the `.deb` file from the [latest release](https://github.com/foss42/apidash/releases/latest) corresponding to you CPU architecture (x64/amd64 or arm64). `cd` to the Downloads folder and execute the following command to install API Dash. @@ -64,7 +64,7 @@ Launch API Dash via `apidash` command or by clicking on the API Dash app icon. ### Red Hat-based Linux Distributions (Fedora, Rocky, AlmaLinux, CentOS, RHEL, etc.) -Download the `.rpm` file from the [latest release](https://github.com/foss42/api-dash/releases/latest) corresponding to you CPU architecture (x86_64 or aarch64/arm64). +Download the `.rpm` file from the [latest release](https://github.com/foss42/apidash/releases/latest) corresponding to you CPU architecture (x86_64 or aarch64/arm64). `cd` to the Downloads folder and execute the following command to install API Dash. diff --git a/README.md b/README.md index 61ac7f01..fc6cbfba 100644 --- a/README.md +++ b/README.md @@ -23,21 +23,21 @@ API Dash can be downloaded from the links below: macOS .dmg - Link + Link Apple Silicon & Intel Link Windows .exe - Link + Link 64-bit Link Linux .deb - Link + Link amd64 Link @@ -47,7 +47,7 @@ API Dash can be downloaded from the links below: .rpm - Link + Link x86_64 Link @@ -62,7 +62,7 @@ API Dash can be downloaded from the links below: Demo Video on Youtube - [Link](https://youtu.be/IQlrgpNpS2s) (In case there is an error loading the embedded video below 👇) -https://github.com/foss42/api-dash/assets/615622/fccc569e-3152-47be-9f94-ceb851ee85a0 +https://github.com/foss42/apidash/assets/615622/fccc569e-3152-47be-9f94-ceb851ee85a0 ## List of Features @@ -101,16 +101,16 @@ Visit [CHANGELOG.md](CHANGELOG.md) ## Provide Feedback, Report Bugs & Request New Features -Just click on the [Issue tab](https://github.com/foss42/api-dash/issues) to raise a new issue in this repo. +Just click on the [Issue tab](https://github.com/foss42/apidash/issues) to raise a new issue in this repo. ## Contribute to API Dash You can contribute to API Dash in any or all of the following ways: -- [Ask a question](https://github.com/foss42/api-dash/discussions) -- [Submit a bug report](https://github.com/foss42/api-dash/issues/new/choose) -- [Request a new feature](https://github.com/foss42/api-dash/issues/new/choose) -- [Suggest ways to improve the developer experience of an existing feature](https://github.com/foss42/api-dash/issues/new/choose) +- [Ask a question](https://github.com/foss42/apidash/discussions) +- [Submit a bug report](https://github.com/foss42/apidash/issues/new/choose) +- [Request a new feature](https://github.com/foss42/apidash/issues/new/choose) +- [Suggest ways to improve the developer experience of an existing feature](https://github.com/foss42/apidash/issues/new/choose) - Add documentation - To add a new feature, resolve an existing issue or add a new test to the project, check out our [Contribution Guidelines](CONTRIBUTING.md). diff --git a/assets/intro.md b/assets/intro.md index e8b61f75..9c2f1be5 100644 --- a/assets/intro.md +++ b/assets/intro.md @@ -40,7 +40,7 @@ Using API Dash, you can easily create & customize your API requests, visually in 7. Notification on save, download and any other user action (UX improvement). 8. Linux builds are now available for API Dash (.deb & .rpm) -.. and various bug fixes & performance improvements. View full changelog [here](https://github.com/foss42/api-dash/blob/main/CHANGELOG.md). +.. and various bug fixes & performance improvements. View full changelog [here](https://github.com/foss42/apidash/blob/main/CHANGELOG.md). #br #br diff --git a/lib/codegen/kotlin/pkg_okhttp.dart b/lib/codegen/kotlin/pkg_okhttp.dart index 260b00d2..5bb90524 100644 --- a/lib/codegen/kotlin/pkg_okhttp.dart +++ b/lib/codegen/kotlin/pkg_okhttp.dart @@ -47,7 +47,7 @@ val body = "${requestModel.requestBody}".toRequestBody(mediaType)\n"""; } for (final queryParam in requestModel.requestParams!) { result = - """$result .addQueryParameter("${queryParam.k}", "${queryParam.v}")\n"""; + """$result .addQueryParameter("${queryParam.name}", "${queryParam.value}")\n"""; } return result; } @@ -58,7 +58,7 @@ val body = "${requestModel.requestBody}".toRequestBody(mediaType)\n"""; return result; } for (final header in requestModel.requestHeaders!) { - result = """$result .addHeader("${header.k}", "${header.v}")\n"""; + result = """$result .addHeader("${header.name}", "${header.value}")\n"""; } return result; } diff --git a/lib/consts.dart b/lib/consts.dart index 40193bfe..e30df21d 100644 --- a/lib/consts.dart +++ b/lib/consts.dart @@ -6,7 +6,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:davi/davi.dart'; const kDiscordUrl = "https://bit.ly/heyfoss"; -const kGitUrl = "https://github.com/foss42/api-dash"; +const kGitUrl = "https://github.com/foss42/apidash"; const kIssueUrl = "$kGitUrl/issues"; final kIsMacOS = !kIsWeb && Platform.isMacOS; @@ -28,6 +28,7 @@ const kWindowTitle = "API Dash"; const kMinWindowSize = Size(900, 600); const kMinInitialWindowWidth = 1200.0; const kMinInitialWindowHeight = 800.0; +const kMinRequestEditorDetailsCardPaneSize = 300.0; const kColorSchemeSeed = Colors.blue; final kFontFamily = GoogleFonts.openSans().fontFamily; @@ -225,16 +226,19 @@ const kMethodsWithBody = [ HTTPVerb.patch, HTTPVerb.delete, ]; + const kDefaultHttpMethod = HTTPVerb.get; const kDefaultContentType = ContentType.json; enum CodegenLanguage { - dartHttp("Dart (http)"), - kotlinOkHttp("Kotlin (OkHttp)"), + dartHttp("Dart (http)", "dart", "dart"), + kotlinOkHttp("Kotlin (okhttp3)", "java", "kt"); pythonHttpClient("Python (http.client)"); - const CodegenLanguage(this.label); + const CodegenLanguage(this.label, this.codeHighlightLang, this.ext); final String label; + final String codeHighlightLang; + final String ext; } const JsonEncoder kEncoder = JsonEncoder.withIndent(' '); diff --git a/lib/main.dart b/lib/main.dart index 91d33c8a..3f72d775 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -13,7 +13,7 @@ void main() async { await setupInitialWindow(); } else { var win = getInitialSize(); - await setupWindow(sz: win.$0, off: win.$1); + await setupWindow(sz: win.$1, off: win.$2); } runApp( ProviderScope( diff --git a/lib/models/kvrow_model.dart b/lib/models/kvrow_model.dart deleted file mode 100644 index 7d3d2125..00000000 --- a/lib/models/kvrow_model.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'package:flutter/material.dart'; - -@immutable -class KVRow { - const KVRow(this.k, this.v); - - final String k; - final dynamic v; - - KVRow copyWith({ - String? k, - dynamic v, - }) { - return KVRow(k ?? this.k, v ?? this.v); - } - - @override - String toString() { - return {k: v}.toString(); - } - - @override - bool operator ==(Object other) { - return other is KVRow && - other.runtimeType == runtimeType && - other.k == k && - other.v == v; - } - - @override - int get hashCode { - return Object.hash( - runtimeType, - k, - v, - ); - } -} diff --git a/lib/models/models.dart b/lib/models/models.dart index af82af6f..3820e3c2 100644 --- a/lib/models/models.dart +++ b/lib/models/models.dart @@ -1,4 +1,4 @@ -export 'kvrow_model.dart'; +export 'name_value_model.dart'; export 'request_model.dart'; export 'response_model.dart'; export 'settings_model.dart'; diff --git a/lib/models/name_value_model.dart b/lib/models/name_value_model.dart new file mode 100644 index 00000000..43a0bd8c --- /dev/null +++ b/lib/models/name_value_model.dart @@ -0,0 +1,17 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:flutter/foundation.dart'; + +part 'name_value_model.freezed.dart'; + +part 'name_value_model.g.dart'; + +@freezed +class NameValueModel with _$NameValueModel { + const factory NameValueModel({ + required String name, + required dynamic value, + }) = _NameValueModel; + + factory NameValueModel.fromJson(Map json) => + _$NameValueModelFromJson(json); +} diff --git a/lib/models/name_value_model.freezed.dart b/lib/models/name_value_model.freezed.dart new file mode 100644 index 00000000..e7d9e8e0 --- /dev/null +++ b/lib/models/name_value_model.freezed.dart @@ -0,0 +1,181 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'name_value_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +NameValueModel _$NameValueModelFromJson(Map json) { + return _NameValueModel.fromJson(json); +} + +/// @nodoc +mixin _$NameValueModel { + String get name => throw _privateConstructorUsedError; + dynamic get value => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $NameValueModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $NameValueModelCopyWith<$Res> { + factory $NameValueModelCopyWith( + NameValueModel value, $Res Function(NameValueModel) then) = + _$NameValueModelCopyWithImpl<$Res, NameValueModel>; + @useResult + $Res call({String name, dynamic value}); +} + +/// @nodoc +class _$NameValueModelCopyWithImpl<$Res, $Val extends NameValueModel> + implements $NameValueModelCopyWith<$Res> { + _$NameValueModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? value = freezed, + }) { + return _then(_value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + value: freezed == value + ? _value.value + : value // ignore: cast_nullable_to_non_nullable + as dynamic, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_NameValueModelCopyWith<$Res> + implements $NameValueModelCopyWith<$Res> { + factory _$$_NameValueModelCopyWith( + _$_NameValueModel value, $Res Function(_$_NameValueModel) then) = + __$$_NameValueModelCopyWithImpl<$Res>; + @override + @useResult + $Res call({String name, dynamic value}); +} + +/// @nodoc +class __$$_NameValueModelCopyWithImpl<$Res> + extends _$NameValueModelCopyWithImpl<$Res, _$_NameValueModel> + implements _$$_NameValueModelCopyWith<$Res> { + __$$_NameValueModelCopyWithImpl( + _$_NameValueModel _value, $Res Function(_$_NameValueModel) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? value = freezed, + }) { + return _then(_$_NameValueModel( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + value: freezed == value + ? _value.value + : value // ignore: cast_nullable_to_non_nullable + as dynamic, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_NameValueModel + with DiagnosticableTreeMixin + implements _NameValueModel { + const _$_NameValueModel({required this.name, required this.value}); + + factory _$_NameValueModel.fromJson(Map json) => + _$$_NameValueModelFromJson(json); + + @override + final String name; + @override + final dynamic value; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'NameValueModel(name: $name, value: $value)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'NameValueModel')) + ..add(DiagnosticsProperty('name', name)) + ..add(DiagnosticsProperty('value', value)); + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_NameValueModel && + (identical(other.name, name) || other.name == name) && + const DeepCollectionEquality().equals(other.value, value)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash( + runtimeType, name, const DeepCollectionEquality().hash(value)); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_NameValueModelCopyWith<_$_NameValueModel> get copyWith => + __$$_NameValueModelCopyWithImpl<_$_NameValueModel>(this, _$identity); + + @override + Map toJson() { + return _$$_NameValueModelToJson( + this, + ); + } +} + +abstract class _NameValueModel implements NameValueModel { + const factory _NameValueModel( + {required final String name, + required final dynamic value}) = _$_NameValueModel; + + factory _NameValueModel.fromJson(Map json) = + _$_NameValueModel.fromJson; + + @override + String get name; + @override + dynamic get value; + @override + @JsonKey(ignore: true) + _$$_NameValueModelCopyWith<_$_NameValueModel> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/models/name_value_model.g.dart b/lib/models/name_value_model.g.dart new file mode 100644 index 00000000..25867df8 --- /dev/null +++ b/lib/models/name_value_model.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'name_value_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_NameValueModel _$$_NameValueModelFromJson(Map json) => + _$_NameValueModel( + name: json['name'] as String, + value: json['value'], + ); + +Map _$$_NameValueModelToJson(_$_NameValueModel instance) => + { + 'name': instance.name, + 'value': instance.value, + }; diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index 13b0ae3c..7e0df5ca 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -1,21 +1,21 @@ import 'package:flutter/foundation.dart'; import 'package:apidash/consts.dart'; import 'package:apidash/utils/utils.dart' show mapToRows, rowsToMap; -import 'kvrow_model.dart'; +import 'name_value_model.dart'; import 'response_model.dart'; @immutable class RequestModel { const RequestModel({ required this.id, - this.method = kDefaultHttpMethod, + this.method = HTTPVerb.get, this.url = "", this.name = "", this.description = "", this.requestTabIndex = 0, this.requestHeaders, this.requestParams, - this.requestBodyContentType = kDefaultContentType, + this.requestBodyContentType = ContentType.json, this.requestBody, this.responseStatus, this.message, @@ -28,8 +28,8 @@ class RequestModel { final String name; final String description; final int requestTabIndex; - final List? requestHeaders; - final List? requestParams; + final List? requestHeaders; + final List? requestParams; final ContentType requestBodyContentType; final String? requestBody; final int? responseStatus; @@ -59,8 +59,8 @@ class RequestModel { String? name, String? description, int? requestTabIndex, - List? requestHeaders, - List? requestParams, + List? requestHeaders, + List? requestParams, ContentType? requestBodyContentType, String? requestBody, int? responseStatus, diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index 9bd24200..baf1242f 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -96,8 +96,8 @@ class CollectionStateNotifier extends StateNotifier?> { String? name, String? description, int? requestTabIndex, - List? requestHeaders, - List? requestParams, + List? requestHeaders, + List? requestParams, ContentType? requestBodyContentType, String? requestBody, int? responseStatus, @@ -132,17 +132,17 @@ class CollectionStateNotifier extends StateNotifier?> { var responseRec = await request(requestModel, defaultUriScheme: defaultUriScheme); late final RequestModel newRequestModel; - if (responseRec.$0 == null) { + if (responseRec.$1 == null) { newRequestModel = requestModel.copyWith( responseStatus: -1, - message: responseRec.$2, + message: responseRec.$3, ); } else { final responseModel = baseResponseModel.fromResponse( - response: responseRec.$0!, - time: responseRec.$1!, + response: responseRec.$1!, + time: responseRec.$2!, ); - int statusCode = responseRec.$0!.statusCode; + int statusCode = responseRec.$1!.statusCode; newRequestModel = requestModel.copyWith( responseStatus: statusCode, message: kResponseCodeReasons[statusCode], @@ -203,4 +203,10 @@ class CollectionStateNotifier extends StateNotifier?> { await hiveHandler.removeUnused(); ref.read(saveDataStateProvider.notifier).update((state) => false); } + + Map exportData() { + return { + "data": state!.map((e) => e.toJson(includeResponse: false)).toList() + }; + } } 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 24f15e03..cf2821f5 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 @@ -25,11 +25,11 @@ class _EditRequestBodyState extends ConsumerState { margin: kPt5o10, child: Column( children: [ - SizedBox( + const SizedBox( height: kHeaderHeight, child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: const [ + children: [ Text( "Select Content Type:", ), 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 beb28802..d1b8f5de 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 @@ -15,7 +15,7 @@ class EditRequestHeaders extends ConsumerStatefulWidget { } class EditRequestHeadersState extends ConsumerState { - late List rows; + late List rows; final random = Random.secure(); late int seed; @@ -37,9 +37,11 @@ class EditRequestHeadersState extends ConsumerState { final length = ref.watch(activeRequestModelProvider .select((value) => value?.requestHeaders?.length)); var rH = ref.read(activeRequestModelProvider)?.requestHeaders; - rows = (rH == null || rH.isEmpty) ? [const KVRow("", "")] : rH; + rows = (rH == null || rH.isEmpty) + ? [const NameValueModel(name: "", value: "")] + : rH; - DaviModel model = DaviModel( + DaviModel model = DaviModel( rows: rows, columns: [ DaviColumn( @@ -49,10 +51,10 @@ class EditRequestHeadersState extends ConsumerState { int idx = row.index; return CellField( keyId: "$activeId-$idx-headers-k-$seed", - initialValue: rows[idx].k, + initialValue: rows[idx].name, hintText: "Add Header Name", onChanged: (value) { - rows[idx] = rows[idx].copyWith(k: value); + rows[idx] = rows[idx].copyWith(name: value); _onFieldChange(activeId!); }, colorScheme: Theme.of(context).colorScheme, @@ -76,10 +78,10 @@ class EditRequestHeadersState extends ConsumerState { int idx = row.index; return CellField( keyId: "$activeId-$idx-headers-v-$seed", - initialValue: rows[idx].v, + initialValue: rows[idx].value, hintText: " Add Header Value", onChanged: (value) { - rows[idx] = rows[idx].copyWith(v: value); + rows[idx] = rows[idx].copyWith(value: value); _onFieldChange(activeId!); }, colorScheme: Theme.of(context).colorScheme, @@ -96,6 +98,9 @@ class EditRequestHeadersState extends ConsumerState { ? kIconRemoveDark : kIconRemoveLight, onTap: () { + if (rows.length == 1) { + return; + } rows.removeAt(row.index); seed = random.nextInt(kRandMax); _onFieldChange(activeId!); @@ -118,7 +123,7 @@ class EditRequestHeadersState extends ConsumerState { Expanded( child: DaviTheme( data: kTableThemeData, - child: Davi(model), + child: Davi(model), ), ), ], @@ -130,7 +135,7 @@ class EditRequestHeadersState extends ConsumerState { padding: const EdgeInsets.only(bottom: 30), child: ElevatedButton.icon( onPressed: () { - rows.add(const KVRow("", "")); + rows.add(const NameValueModel(name: "", value: "")); _onFieldChange(activeId!); }, icon: const Icon(Icons.add), 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 fd03d487..e9c6d2cb 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 @@ -16,7 +16,7 @@ class EditRequestURLParams extends ConsumerStatefulWidget { } class EditRequestURLParamsState extends ConsumerState { - late List rows; + late List rows; final random = Random.secure(); late int seed; @@ -38,9 +38,11 @@ class EditRequestURLParamsState extends ConsumerState { final length = ref.watch(activeRequestModelProvider .select((value) => value?.requestParams?.length)); var rP = ref.read(activeRequestModelProvider)?.requestParams; - rows = (rP == null || rP.isEmpty) ? [const KVRow("", "")] : rP; + rows = (rP == null || rP.isEmpty) + ? [const NameValueModel(name: "", value: "")] + : rP; - DaviModel model = DaviModel( + DaviModel model = DaviModel( rows: rows, columns: [ DaviColumn( @@ -50,10 +52,10 @@ class EditRequestURLParamsState extends ConsumerState { int idx = row.index; return CellField( keyId: "$activeId-$idx-params-k-$seed", - initialValue: rows[idx].k, + initialValue: rows[idx].name, hintText: "Add URL Parameter", onChanged: (value) { - rows[idx] = rows[idx].copyWith(k: value); + rows[idx] = rows[idx].copyWith(name: value); _onFieldChange(activeId!); }, colorScheme: Theme.of(context).colorScheme, @@ -77,10 +79,10 @@ class EditRequestURLParamsState extends ConsumerState { int idx = row.index; return CellField( keyId: "$activeId-$idx-params-v-$seed", - initialValue: rows[idx].v, + initialValue: rows[idx].value, hintText: "Add Value", onChanged: (value) { - rows[idx] = rows[idx].copyWith(v: value); + rows[idx] = rows[idx].copyWith(value: value); _onFieldChange(activeId!); }, colorScheme: Theme.of(context).colorScheme, @@ -97,6 +99,9 @@ class EditRequestURLParamsState extends ConsumerState { ? kIconRemoveDark : kIconRemoveLight, onTap: () { + if (rows.length == 1) { + return; + } rows.removeAt(row.index); seed = random.nextInt(kRandMax); _onFieldChange(activeId!); @@ -119,7 +124,7 @@ class EditRequestURLParamsState extends ConsumerState { Expanded( child: DaviTheme( data: kTableThemeData, - child: Davi(model), + child: Davi(model), ), ), ], @@ -131,7 +136,7 @@ class EditRequestURLParamsState extends ConsumerState { padding: const EdgeInsets.only(bottom: 30), child: ElevatedButton.icon( onPressed: () { - rows.add(const KVRow("", "")); + rows.add(const NameValueModel(name: "", value: "")); _onFieldChange(activeId!); }, icon: const Icon(Icons.add), diff --git a/lib/screens/home_page/editor_pane/editor_pane.dart b/lib/screens/home_page/editor_pane/editor_pane.dart index daba1d62..4ff5e17b 100644 --- a/lib/screens/home_page/editor_pane/editor_pane.dart +++ b/lib/screens/home_page/editor_pane/editor_pane.dart @@ -28,8 +28,8 @@ class _RequestEditorPaneState extends ConsumerState { } else { return Padding( padding: kIsMacOS ? kPt24o8 : kP8, - child: Column( - children: const [ + child: const Column( + children: [ EditorPaneRequestURLCard(), kVSpacer10, Expanded( diff --git a/lib/screens/home_page/editor_pane/url_card.dart b/lib/screens/home_page/editor_pane/url_card.dart index 2647695a..e99dac2b 100644 --- a/lib/screens/home_page/editor_pane/url_card.dart +++ b/lib/screens/home_page/editor_pane/url_card.dart @@ -28,13 +28,13 @@ class _EditorPaneRequestURLCardState extends State { ), borderRadius: kBorderRadius12, ), - child: Padding( - padding: const EdgeInsets.symmetric( + child: const Padding( + padding: EdgeInsets.symmetric( vertical: 5, horizontal: 20, ), child: Row( - children: const [ + children: [ DropdownButtonHTTPMethod(), kHSpacer20, Expanded( diff --git a/lib/screens/home_page/home_page.dart b/lib/screens/home_page/home_page.dart index 8b94b598..ae3a7598 100644 --- a/lib/screens/home_page/home_page.dart +++ b/lib/screens/home_page/home_page.dart @@ -13,8 +13,8 @@ class HomePage extends StatefulWidget { class HomePageState extends State { @override Widget build(BuildContext context) { - return Column( - children: const [ + return const Column( + children: [ Expanded( child: DashboardSplitView( sidebarWidget: CollectionPane(), diff --git a/lib/screens/settings_page.dart b/lib/screens/settings_page.dart index bc4e22f8..c71de31f 100644 --- a/lib/screens/settings_page.dart +++ b/lib/screens/settings_page.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:apidash/providers/providers.dart'; -import 'package:apidash/widgets/widgets.dart'; +import '../providers/providers.dart'; +import '../widgets/widgets.dart'; +import '../utils/utils.dart'; import 'package:apidash/consts.dart'; class SettingsPage extends ConsumerStatefulWidget { @@ -73,6 +74,24 @@ class _SettingsPageState extends ConsumerState { .update(saveResponses: value); }, ), + ListTile( + contentPadding: EdgeInsets.zero, + hoverColor: kColorTransparent, + title: const Text('Export Collection'), + subtitle: const Text('Export your collection to a JSON file'), + trailing: FilledButton( + onPressed: () async { + var data = ref + .read(collectionStateNotifierProvider.notifier) + .exportData(); + var pth = await getFileDownloadpath(null, "json"); + if (pth != null) { + await saveFile(pth, jsonMapToBytes(data)); + } + }, + child: const Text("Export Data"), + ), + ), ListTile( contentPadding: EdgeInsets.zero, hoverColor: kColorTransparent, diff --git a/lib/services/http_service.dart b/lib/services/http_service.dart index 2a9ca1ad..1f736d6d 100644 --- a/lib/services/http_service.dart +++ b/lib/services/http_service.dart @@ -7,66 +7,59 @@ import 'package:apidash/models/models.dart'; import 'package:apidash/consts.dart'; Future<(http.Response?, Duration?, String?)> request( - RequestModel requestModel, - {String defaultUriScheme = kDefaultUriScheme} -) async { - (Uri?, String?) uriRec = getValidRequestUri(requestModel.url, - requestModel.requestParams, - defaultUriScheme: defaultUriScheme); - if(uriRec.$0 != null){ - Uri requestUrl = uriRec.$0!; + RequestModel requestModel, { + String defaultUriScheme = kDefaultUriScheme, +}) async { + (Uri?, String?) uriRec = getValidRequestUri( + requestModel.url, + requestModel.requestParams, + defaultUriScheme: defaultUriScheme, + ); + if (uriRec.$1 != null) { + Uri requestUrl = uriRec.$1!; Map headers = rowsToMap(requestModel.requestHeaders) ?? {}; http.Response response; String? body; - try { + try { var requestBody = requestModel.requestBody; - if(kMethodsWithBody.contains(requestModel.method) && requestBody != null){ + if (kMethodsWithBody.contains(requestModel.method) && + requestBody != null) { var contentLength = utf8.encode(requestBody).length; - if (contentLength > 0){ + if (contentLength > 0) { body = requestBody; headers[HttpHeaders.contentLengthHeader] = contentLength.toString(); - headers[HttpHeaders.contentTypeHeader] = kContentTypeMap[requestModel.requestBodyContentType] ?? ""; + headers[HttpHeaders.contentTypeHeader] = + kContentTypeMap[requestModel.requestBodyContentType] ?? ""; } } Stopwatch stopwatch = Stopwatch()..start(); - switch(requestModel.method){ + switch (requestModel.method) { case HTTPVerb.get: - response = await http.get(requestUrl, - headers: headers); + response = await http.get(requestUrl, headers: headers); break; case HTTPVerb.head: - response = await http.head(requestUrl, - headers: headers); + response = await http.head(requestUrl, headers: headers); break; case HTTPVerb.post: - response = await http.post(requestUrl, - headers: headers, - body: body); + response = await http.post(requestUrl, headers: headers, body: body); break; case HTTPVerb.put: - response = await http.put(requestUrl, - headers: headers, - body: body); + response = await http.put(requestUrl, headers: headers, body: body); break; case HTTPVerb.patch: - response = await http.patch(requestUrl, - headers: headers, - body: body); + response = await http.patch(requestUrl, headers: headers, body: body); break; case HTTPVerb.delete: - response = await http.delete(requestUrl, - headers: headers, - body: body); + response = + await http.delete(requestUrl, headers: headers, body: body); break; } - stopwatch.stop(); + stopwatch.stop(); return (response, stopwatch.elapsed, null); - } - catch (e) { + } catch (e) { return (null, null, e.toString()); } - } - else { - return (null, null, uriRec.$1); + } else { + return (null, null, uriRec.$2); } } diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index e626c53f..e12f2dcc 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -1,7 +1,7 @@ import 'dart:typed_data'; import 'dart:convert'; +import '../models/models.dart'; import '../consts.dart'; -import 'package:apidash/models/models.dart' show KVRow; String humanizeDuration(Duration? duration) { if (duration == null) { @@ -60,30 +60,31 @@ String padMultilineString(String text, int padding, return lines.join("\n"); } -Map? rowsToMap(List? kvRows, {bool isHeader = false}) { +Map? rowsToMap(List? kvRows, + {bool isHeader = false}) { if (kvRows == null) { return null; } Map finalMap = {}; for (var row in kvRows) { - if (row.k.trim() != "") { - String key = row.k; + if (row.name.trim() != "") { + String key = row.name; if (isHeader) { key = key.toLowerCase(); } - finalMap[key] = row.v.toString(); + finalMap[key] = row.value.toString(); } } return finalMap; } -List? mapToRows(Map? kvMap) { +List? mapToRows(Map? kvMap) { if (kvMap == null) { return null; } - List finalRows = []; + List finalRows = []; for (var k in kvMap.keys) { - finalRows.add(KVRow(k, kvMap[k])); + finalRows.add(NameValueModel(name: k, value: kvMap[k])); } return finalRows; } @@ -97,3 +98,14 @@ Uint8List? stringToBytes(String? text) { return bytes; } } + +Uint8List jsonMapToBytes(Map? map) { + if (map == null) { + return Uint8List.fromList([]); + } else { + String text = kEncoder.convert(map); + var l = utf8.encode(text); + var bytes = Uint8List.fromList(l); + return bytes; + } +} diff --git a/lib/utils/http_utils.dart b/lib/utils/http_utils.dart index 31437e2f..99f922a3 100644 --- a/lib/utils/http_utils.dart +++ b/lib/utils/http_utils.dart @@ -3,7 +3,7 @@ import 'dart:io'; import 'package:collection/collection.dart' show mergeMaps; import 'package:http_parser/http_parser.dart'; import 'package:xml/xml.dart'; -import 'package:apidash/models/models.dart' show KVRow; +import '../models/models.dart'; import 'convert_utils.dart' show rowsToMap; import '../consts.dart'; @@ -44,8 +44,8 @@ MediaType? getMediaTypeFromHeaders(Map? headers) { } (String?, bool) getUriScheme(Uri uri) { - if(uri.hasScheme){ - if(kSupportedUriSchemes.contains(uri.scheme)){ + if (uri.hasScheme) { + if (kSupportedUriSchemes.contains(uri.scheme)) { return (uri.scheme, true); } return (uri.scheme, false); @@ -54,37 +54,34 @@ MediaType? getMediaTypeFromHeaders(Map? headers) { } (Uri?, String?) getValidRequestUri( - String? url, - List? requestParams, - {String defaultUriScheme = kDefaultUriScheme} -) { + String? url, List? requestParams, + {String defaultUriScheme = kDefaultUriScheme}) { url = url?.trim(); - if(url == null || url == ""){ + if (url == null || url == "") { return (null, "URL is missing!"); } - Uri? uri = Uri.tryParse(url); - if(uri == null){ + Uri? uri = Uri.tryParse(url); + if (uri == null) { return (null, "Check URL (malformed)"); } (String?, bool) urlScheme = getUriScheme(uri); - if(urlScheme.$0 != null){ - if (!urlScheme.$1){ - return (null, "Unsupported URL Scheme (${urlScheme.$0})"); + if (urlScheme.$1 != null) { + if (!urlScheme.$2) { + return (null, "Unsupported URL Scheme (${urlScheme.$1})"); } - } - else { + } else { url = "$defaultUriScheme://$url"; } - uri = Uri.parse(url); - if (uri.hasFragment){ + uri = Uri.parse(url); + if (uri.hasFragment) { uri = uri.removeFragment(); } Map? queryParams = rowsToMap(requestParams); - if(queryParams != null){ - if(uri.hasQuery){ + if (queryParams != null) { + if (uri.hasQuery) { Map urlQueryParams = uri.queryParameters; queryParams = mergeMaps(urlQueryParams, queryParams); } @@ -93,48 +90,58 @@ MediaType? getMediaTypeFromHeaders(Map? headers) { return (uri, null); } -(List, String?) getResponseBodyViewOptions(MediaType? mediaType){ - if(mediaType != null){ +(List, String?) getResponseBodyViewOptions( + MediaType? mediaType) { + if (mediaType != null) { var type = mediaType.type; var subtype = mediaType.subtype; - if(kResponseBodyViewOptions.containsKey(type)){ - if (kResponseBodyViewOptions[type]!.containsKey(subtype)){ - return (kResponseBodyViewOptions[type]![subtype]!, kCodeHighlighterMap[subtype] ?? subtype); + if (kResponseBodyViewOptions.containsKey(type)) { + if (kResponseBodyViewOptions[type]!.containsKey(subtype)) { + return ( + kResponseBodyViewOptions[type]![subtype]!, + kCodeHighlighterMap[subtype] ?? subtype + ); } - if(subtype.contains(kSubTypeJson)){ + if (subtype.contains(kSubTypeJson)) { subtype = kSubTypeJson; } - if(subtype.contains(kSubTypeXml)){ + if (subtype.contains(kSubTypeXml)) { subtype = kSubTypeXml; } - if (kResponseBodyViewOptions[type]!.containsKey(subtype)){ - return (kResponseBodyViewOptions[type]![subtype]!, kCodeHighlighterMap[subtype] ?? subtype); + if (kResponseBodyViewOptions[type]!.containsKey(subtype)) { + return ( + kResponseBodyViewOptions[type]![subtype]!, + kCodeHighlighterMap[subtype] ?? subtype + ); } - return (kResponseBodyViewOptions[type]![kSubTypeDefaultViewOptions]!, subtype); + return ( + kResponseBodyViewOptions[type]![kSubTypeDefaultViewOptions]!, + subtype + ); } } return (kNoBodyViewOptions, null); } -String? formatBody(String? body, MediaType? mediaType){ - if(mediaType != null && body != null){ +String? formatBody(String? body, MediaType? mediaType) { + if (mediaType != null && body != null) { var subtype = mediaType.subtype; try { - if(subtype.contains(kSubTypeJson)){ + if (subtype.contains(kSubTypeJson)) { final tmp = jsonDecode(body); String result = kEncoder.convert(tmp); return result; } - if(subtype.contains(kSubTypeXml)){ + if (subtype.contains(kSubTypeXml)) { final document = XmlDocument.parse(body); String result = document.toXmlString(pretty: true, indent: ' '); return result; } - if(subtype == kSubTypeHtml){ + if (subtype == kSubTypeHtml) { var len = body.length; var lines = kSplitter.convert(body); var numOfLines = lines.length; - if(numOfLines !=0 && len/numOfLines <= kCodeCharsPerLineLimit){ + if (numOfLines != 0 && len / numOfLines <= kCodeCharsPerLineLimit) { return body; } } @@ -143,4 +150,4 @@ String? formatBody(String? body, MediaType? mediaType){ } } return null; -} \ No newline at end of file +} diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index da50bab0..04eae938 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -2,3 +2,4 @@ export 'ui_utils.dart'; export 'convert_utils.dart'; export 'http_utils.dart'; export 'file_utils.dart'; +export 'window_utils.dart'; diff --git a/lib/utils/window_utils.dart b/lib/utils/window_utils.dart new file mode 100644 index 00000000..34c1984d --- /dev/null +++ b/lib/utils/window_utils.dart @@ -0,0 +1,18 @@ +bool showButtonLabelsInBodySuccess(int options, double maxWidth) { + switch (options) { + case 0: + return true; + case 1: + return (maxWidth < 300) ? false : true; + case 2: + return (maxWidth < 400) ? false : true; + case 3: + return (maxWidth < 500) ? false : true; + default: + return false; + } +} + +bool showButtonLabelsInViewCodePane(double maxWidth) { + return (maxWidth < 400) ? false : true; +} diff --git a/lib/widgets/buttons.dart b/lib/widgets/buttons.dart index 6d5365ca..10d0c59c 100644 --- a/lib/widgets/buttons.dart +++ b/lib/widgets/buttons.dart @@ -104,12 +104,14 @@ class SaveInDownloadsButton extends StatefulWidget { super.key, this.content, this.mimeType, + this.ext, this.name, this.showLabel = true, }); final Uint8List? content; final String? mimeType; + final String? ext; final String? name; final bool showLabel; @@ -129,10 +131,9 @@ class _SaveInDownloadsButtonState extends State { onPressed: (widget.content != null) ? () async { var message = ""; - var ext = getFileExtension(widget.mimeType); var path = await getFileDownloadpath( widget.name, - ext, + widget.ext ?? getFileExtension(widget.mimeType), ); if (path != null) { try { diff --git a/lib/widgets/code_previewer.dart b/lib/widgets/code_previewer.dart index a073fb21..b4e7223b 100644 --- a/lib/widgets/code_previewer.dart +++ b/lib/widgets/code_previewer.dart @@ -6,7 +6,7 @@ import 'error_message.dart'; (String, bool) sanitize(String input) { bool limitedLines = false; int tabSize = 4; - var lines = kSplitter.convert(input); + var lines = kSplitter.convert(input); if (lines.length > kCodePreviewLinesLimit) { lines = lines.sublist(0, kCodePreviewLinesLimit); limitedLines = true; @@ -67,7 +67,12 @@ class _CodePreviewerState extends State { textStyle = textStyle.merge(widget.textStyle); } processed = sanitize(widget.code); - spans = asyncGenerateSpans(processed.$0, widget.language, widget.theme, processed.$1); + spans = asyncGenerateSpans( + processed.$1, + widget.language, + widget.theme, + processed.$2, + ); } @override @@ -131,12 +136,14 @@ class _CodePreviewerState extends State { } } -Future> asyncGenerateSpans( - String code, String? language, Map theme, bool limitedLines) async { +Future> asyncGenerateSpans(String code, String? language, + Map theme, bool limitedLines) async { var parsed = highlight.parse(code, language: language); var spans = convert(parsed.nodes!, theme); - if(limitedLines) { - spans.add(const TextSpan(text: "\n... more.\nPreview ends here ($kCodePreviewLinesLimit lines).\nYou can check Raw for full result.")); + if (limitedLines) { + spans.add(const TextSpan( + text: + "\n... more.\nPreview ends here ($kCodePreviewLinesLimit lines).\nYou can check Raw for full result.")); } return spans; } diff --git a/lib/widgets/codegen_previewer.dart b/lib/widgets/codegen_previewer.dart index 5833d547..a4083661 100644 --- a/lib/widgets/codegen_previewer.dart +++ b/lib/widgets/codegen_previewer.dart @@ -135,48 +135,55 @@ class _ViewCodePaneState extends State { borderRadius: kBorderRadius8, ); - return Padding( - padding: kP10, - child: Column( - children: [ - SizedBox( - height: kHeaderHeight, - child: Row( - children: [ - Expanded( - child: Text( - "Code", - style: Theme.of(context).textTheme.titleMedium, + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + var showLabel = showButtonLabelsInViewCodePane( + constraints.maxWidth, + ); + return Padding( + padding: kP10, + child: Column( + children: [ + SizedBox( + height: kHeaderHeight, + child: Row( + children: [ + Expanded( + child: DropdownButtonCodegenLanguage( + codegenLanguage: widget.codegenLanguage, + onChanged: widget.onChangedCodegenLanguage, + ), + ), + CopyButton( + toCopy: widget.code, + showLabel: showLabel, + ), + SaveInDownloadsButton( + content: stringToBytes(widget.code), + ext: widget.codegenLanguage.ext, + showLabel: showLabel, + ) + ], + ), + ), + kVSpacer10, + Expanded( + child: Container( + width: double.maxFinite, + padding: kP8, + decoration: textContainerdecoration, + child: CodeGenPreviewer( + code: widget.code, + theme: codeTheme, + language: widget.codegenLanguage.codeHighlightLang, + textStyle: kCodeStyle, ), ), - DropdownButtonCodegenLanguage( - codegenLanguage: widget.codegenLanguage, - onChanged: widget.onChangedCodegenLanguage, - ), - CopyButton(toCopy: widget.code), - SaveInDownloadsButton( - content: stringToBytes(widget.code), - mimeType: "application/vnd.dart", - ) - ], - ), - ), - kVSpacer10, - Expanded( - child: Container( - width: double.maxFinite, - padding: kP8, - decoration: textContainerdecoration, - child: CodeGenPreviewer( - code: widget.code, - theme: codeTheme, - language: 'dart', - textStyle: kCodeStyle, ), - ), + ], ), - ], - ), + ); + }, ); } } diff --git a/lib/widgets/response_widgets.dart b/lib/widgets/response_widgets.dart index 6523546a..5bcd9c7d 100644 --- a/lib/widgets/response_widgets.dart +++ b/lib/widgets/response_widgets.dart @@ -339,8 +339,8 @@ class _ResponseBodyState extends State { } var responseBodyView = getResponseBodyViewOptions(mediaType); - var options = responseBodyView.$0; - var highlightLanguage = responseBodyView.$1; + var options = responseBodyView.$1; + var highlightLanguage = responseBodyView.$2; if (formattedBody == null) { options = [...options]; @@ -400,18 +400,10 @@ class _BodySuccessState extends State { return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { - var showLabel = false; - switch (widget.options.length) { - case 1: - showLabel = (constraints.maxWidth < 300) ? false : true; - break; - case 2: - showLabel = (constraints.maxWidth < 400) ? false : true; - break; - case 3: - showLabel = (constraints.maxWidth < 500) ? false : true; - break; - } + var showLabel = showButtonLabelsInBodySuccess( + widget.options.length, + constraints.maxWidth, + ); return Padding( padding: kP10, child: Column( diff --git a/lib/widgets/splitviews.dart b/lib/widgets/splitviews.dart index b5c2d917..b4985371 100644 --- a/lib/widgets/splitviews.dart +++ b/lib/widgets/splitviews.dart @@ -76,8 +76,8 @@ class EqualSplitView extends StatefulWidget { class _EqualSplitViewState extends State { final MultiSplitViewController _controller = MultiSplitViewController( areas: [ - Area(minimalSize: 300), - Area(minimalSize: 300), + Area(minimalSize: kMinRequestEditorDetailsCardPaneSize), + Area(minimalSize: kMinRequestEditorDetailsCardPaneSize), ], ); diff --git a/pubspec.lock b/pubspec.lock index cf967534..f6146ef3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,58 +5,58 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "98d1d33ed129b372846e862de23a0fc365745f4d7b5e786ce667fcbbb7ac5c07" + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a url: "https://pub.dev" source: hosted - version: "55.0.0" + version: "61.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: "881348aed9b0b425882c97732629a6a31093c8ff20fc4b3b03fb9d3d50a3a126" + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 url: "https://pub.dev" source: hosted - version: "5.7.1" + version: "5.13.0" archive: dependency: transitive description: name: archive - sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d + sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" url: "https://pub.dev" source: hosted - version: "3.3.6" + version: "3.3.7" args: dependency: transitive description: name: args - sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.2" async: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" audio_session: dependency: transitive description: name: audio_session - sha256: "655343841a723646f74932215c5785ef7156b76d2de4b99bcd3205476f08dc61" + sha256: "8a2bc5e30520e18f3fb0e366793d78057fb64cd5287862c76af0c8771f2a52ad" url: "https://pub.dev" source: hosted - version: "0.1.15" + version: "0.1.16" axis_layout: dependency: transitive description: name: axis_layout - sha256: "645f76e306a48e1075f8f142bd8ef12c6ceb25cb8d8fdc53aa9d5b4e08a7994a" + sha256: "9ba44f279f39121065d811e72da892de86f5613d68eb0b295f60d021ea8f2a59" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.1" boolean_selector: dependency: transitive description: @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: build - sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" build_config: dependency: transitive description: @@ -81,30 +81,78 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "6c4dd11d05d056e76320b828a1db0fc01ccd376922526f8e9d6c796a5adbac20" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" + url: "https://pub.dev" + source: hosted + version: "2.4.6" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" + url: "https://pub.dev" + source: hosted + version: "7.2.10" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: ff627b645b28fb8bdb69e645f910c2458fd6b65f6585c3a53e0626024897dedf + url: "https://pub.dev" + source: hosted + version: "8.6.2" characters: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" checked_yaml: dependency: transitive description: name: checked_yaml - sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" cli_util: dependency: transitive description: name: cli_util - sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c" + sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7 url: "https://pub.dev" source: hosted - version: "0.3.5" + version: "0.4.0" clock: dependency: transitive description: @@ -113,14 +161,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189" + url: "https://pub.dev" + source: hosted + version: "4.5.0" collection: dependency: "direct main" description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.2" convert: dependency: transitive description: @@ -141,26 +197,26 @@ packages: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" dart_style: dependency: transitive description: name: dart_style - sha256: "6d691edde054969f0e0f26abb1b30834b5138b963793e56f69d3a9a4435e6352" + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.2" davi: dependency: "direct main" description: name: davi - sha256: c47ff1da5bb0930a8c725030af2b14528e470ff2e28a863c4f3d710133bdbe7e + sha256: "4105870281c4c33e8e017e21e212b96fd2637b4c1a35b2a56f14aaa4acdf6f0d" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.4.1" eventify: dependency: transitive description: @@ -181,18 +237,26 @@ packages: dependency: transitive description: name: ffi - sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.0" file: dependency: transitive description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "7.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -202,34 +266,34 @@ packages: dependency: "direct dev" description: name: flutter_launcher_icons - sha256: "02dcaf49d405f652b7160e882bacfc02cb497041bb2eab2a49b1c393cf9aac12" + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" url: "https://pub.dev" source: hosted - version: "0.12.0" + version: "0.13.1" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" flutter_markdown: dependency: "direct main" description: name: flutter_markdown - sha256: "7b25c10de1fea883f3c4f9b8389506b54053cd00807beab69fd65c8653a2711f" + sha256: "2b206d397dd7836ea60035b2d43825c8a303a76a5098e66f42d55a753e18d431" url: "https://pub.dev" source: hosted - version: "0.6.14" + version: "0.6.17+1" flutter_riverpod: dependency: "direct main" description: name: flutter_riverpod - sha256: "812dfbb87af51e73e68ea038bcfd1c732078d6838d3388d03283db7dec0d1e5f" + sha256: b6cb0041c6c11cefb2dcb97ef436eba43c6d41287ac6d8ca93e02a497f53a4f3 url: "https://pub.dev" source: hosted - version: "2.3.4" + version: "2.3.7" flutter_test: dependency: "direct dev" description: flutter @@ -240,14 +304,22 @@ packages: description: flutter source: sdk version: "0.0.0" - freezed_annotation: - dependency: transitive + freezed: + dependency: "direct dev" description: - name: freezed_annotation - sha256: aeac15850ef1b38ee368d4c53ba9a847e900bb2c53a4db3f6881cbb3cb684338 + name: freezed + sha256: "2df89855fe181baae3b6d714dc3c4317acf4fccd495a6f36e5e00f24144c6c3b" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.1" + freezed_annotation: + dependency: "direct main" + description: + name: freezed_annotation + sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d + url: "https://pub.dev" + source: hosted + version: "2.4.1" frontend_server_client: dependency: transitive description: @@ -260,18 +332,26 @@ packages: dependency: transitive description: name: glob - sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" google_fonts: dependency: "direct main" description: name: google_fonts - sha256: "927573f2e8a8d65c17931e21918ad0ab0666b1b636537de7c4932bdb487b190f" + sha256: e20ff62b158b96f392bfc8afe29dee1503c94fbea2cbe8186fd59b756b8ae982 url: "https://pub.dev" source: hosted - version: "4.0.3" + version: "5.1.0" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" highlighter: dependency: "direct main" description: @@ -308,10 +388,10 @@ packages: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_multi_server: dependency: transitive description: @@ -332,10 +412,10 @@ packages: dependency: transitive description: name: image - sha256: "483a389d6ccb292b570c31b3a193779b1b0178e7eb571986d9a49904b6861227" + sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf url: "https://pub.dev" source: hosted - version: "4.0.15" + version: "4.0.17" io: dependency: transitive description: @@ -348,34 +428,34 @@ packages: dependency: "direct main" description: name: jinja - sha256: "7b6fd9b8420e9db923a0852aa43f688b99381f45caee60b3ba8dcc445d5e60b9" + sha256: bec5ecbc8f067d2092d8f25c7f861c7875a29c935cffb7628acd4038aef0f129 url: "https://pub.dev" source: hosted - version: "0.4.2" + version: "0.5.0" js: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" json_annotation: - dependency: transitive + dependency: "direct main" description: name: json_annotation - sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 url: "https://pub.dev" source: hosted - version: "4.8.0" + version: "4.8.1" json_serializable: - dependency: transitive + dependency: "direct dev" description: name: json_serializable - sha256: dadc08bd61f72559f938dd08ec20dbfec6c709bba83515085ea943d2078d187a + sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969 url: "https://pub.dev" source: hosted - version: "6.6.1" + version: "6.7.1" just_audio: dependency: "direct main" description: @@ -388,10 +468,10 @@ packages: dependency: "direct main" description: name: just_audio_mpv - sha256: "98ac36712f3fe4fb0cf545f29c250fbd55e52c8445a4b0a4ee0bc9322f192797" + sha256: d6e4e9fd20bfb9d2fd5e3dcd7906c90ed07f83d1d2f44f31204160821ab62fed url: "https://pub.dev" source: hosted - version: "0.1.6" + version: "0.1.7" just_audio_platform_interface: dependency: transitive description: @@ -420,58 +500,58 @@ packages: dependency: transitive description: name: lints - sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.1" logging: dependency: transitive description: name: logging - sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" lottie: dependency: "direct main" description: name: lottie - sha256: "23522951540d20a57a60202ed7022e6376bed206a4eee1c347a91f58bd57eb9f" + sha256: b8bdd54b488c54068c57d41ae85d02808da09e2bee8b8dd1f59f441e7efa60cd url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.6.0" markdown: dependency: "direct main" description: name: markdown - sha256: "8e332924094383133cee218b676871f42db2514f1f6ac617b6cf6152a7faab8e" + sha256: acf35edccc0463a9d7384e437c015a3535772e09714cf60e07eeef3a15870dcd url: "https://pub.dev" source: hosted - version: "7.1.0" + version: "7.1.1" matcher: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: @@ -524,90 +604,90 @@ packages: dependency: "direct main" description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: "direct main" description: name: path_provider - sha256: c7edf82217d4b2952b2129a61d3ad60f1075b9299e629e149a8d2e39c2e6aad4 + sha256: "909b84830485dbcd0308edf6f7368bc8fd76afa26a270420f34cabea2a6467a0" url: "https://pub.dev" source: hosted - version: "2.0.14" + version: "2.1.0" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "7623b7d4be0f0f7d9a8b5ee6879fc13e4522d4c875ab86801dee4af32b54b83e" + sha256: "5d44fc3314d969b84816b569070d7ace0f1dea04bd94a83f74c4829615d22ad8" url: "https://pub.dev" source: hosted - version: "2.0.23" + version: "2.1.0" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: eec003594f19fe2456ea965ae36b3fc967bc5005f508890aafe31fa75e41d972 + sha256: "1b744d3d774e5a879bb76d6cd1ecee2ba2c6960c03b1020cd35212f6aa267ac5" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.3.0" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: "525ad5e07622d19447ad740b1ed5070031f7a5437f44355ae915ff56e986429a" + sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3 url: "https://pub.dev" source: hosted - version: "2.1.9" + version: "2.2.0" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84 url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.1.0" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: "642ddf65fde5404f83267e8459ddb4556316d3ee6d511ed193357e25caa3632d" + sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" petitparser: dependency: transitive description: name: petitparser - sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.4.0" platform: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "57c07bf82207aee366dfaa3867b3164e4f03a238a461a11b0e8a3a510d51203d" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" pointycastle: dependency: transitive description: name: pointycastle - sha256: c3120a968135aead39699267f4c74bc9a08e4e909e86bc1b0af5bfd78691123c + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" url: "https://pub.dev" source: hosted - version: "3.7.2" + version: "3.7.3" pool: dependency: transitive description: @@ -616,38 +696,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" - process: - dependency: transitive - description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" - url: "https://pub.dev" - source: hosted - version: "4.2.4" pub_semver: dependency: transitive description: name: pub_semver - sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: ec85d7d55339d85f44ec2b682a82fea340071e8978257e5a43e69f79e98ef50c + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.2.3" riverpod: dependency: transitive description: name: riverpod - sha256: "77ab3bcd084bb19fa8717a526217787c725d7f5be938404c7839cd760fdf6ae5" + sha256: b0657b5b30c81a3184bdaab353045f0a403ebd60bb381591a8b7ad77dcade793 url: "https://pub.dev" source: hosted - version: "2.3.4" + version: "2.3.7" rxdart: dependency: transitive description: @@ -660,42 +732,42 @@ packages: dependency: transitive description: name: screen_retriever - sha256: "4931f226ca158123ccd765325e9fbf360bfed0af9b460a10f960f9bb13d58323" + sha256: "63694235c194d0d953f698fbb04471eb6c8d0e6bbb283a369b40414ed07ef83a" url: "https://pub.dev" source: hosted - version: "0.1.6" + version: "0.1.8" shelf: dependency: transitive description: name: shelf - sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler - sha256: aef74dc9195746a384843102142ab65b6a4735bb3beea791e63527b88cc83306 + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" shelf_static: dependency: transitive description: name: shelf_static - sha256: e792b76b96a36d4a41b819da593aff4bdd413576b3ba6150df5d8d9996d2e74c + sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" sky_engine: dependency: transitive description: flutter @@ -705,18 +777,18 @@ packages: dependency: transitive description: name: source_gen - sha256: c2bea18c95cfa0276a366270afaa2850b09b4a76db95d546f3d003dcc7011298 + sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 url: "https://pub.dev" source: hosted - version: "1.2.7" + version: "1.4.0" source_helper: dependency: transitive description: name: source_helper - sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" url: "https://pub.dev" source: hosted - version: "1.3.3" + version: "1.3.4" source_map_stack_trace: dependency: transitive description: @@ -737,10 +809,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: @@ -753,10 +825,10 @@ packages: dependency: transitive description: name: state_notifier - sha256: "8fe42610f179b843b12371e40db58c9444f8757f8b69d181c97e50787caed289" + sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb url: "https://pub.dev" source: hosted - version: "0.7.2+1" + version: "1.0.0" stream_channel: dependency: transitive description: @@ -765,6 +837,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" string_scanner: dependency: transitive description: @@ -785,26 +865,26 @@ packages: dependency: "direct dev" description: name: test - sha256: a5fcd2d25eeadbb6589e80198a47d6a464ba3e2049da473943b8af9797900c2d + sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46" url: "https://pub.dev" source: hosted - version: "1.22.0" + version: "1.24.3" test_api: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.6.0" test_core: dependency: transitive description: name: test_core - sha256: "0ef9755ec6d746951ba0aabe62f874b707690b5ede0fecc818b138fcc9b14888" + sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e" url: "https://pub.dev" source: hosted - version: "0.4.20" + version: "0.5.3" textwrap: dependency: transitive description: @@ -813,78 +893,86 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" typed_data: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" url_launcher: dependency: "direct main" description: name: url_launcher - sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" + sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e" url: "https://pub.dev" source: hosted - version: "6.1.10" + version: "6.1.12" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: dd729390aa936bf1bdf5cd1bc7468ff340263f80a2c4f569416507667de8e3c8 + sha256: "3dd2388cc0c42912eee04434531a26a82512b9cb1827e0214430c9bcbddfe025" url: "https://pub.dev" source: hosted - version: "6.0.26" + version: "6.0.38" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "3dedc66ca3c0bef9e6a93c0999aee102556a450afcc1b7bcfeace7a424927d92" + sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" url: "https://pub.dev" source: hosted - version: "6.1.3" + version: "6.1.4" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "206fb8334a700ef7754d6a9ed119e7349bc830448098f21a69bf1b4ed038cabc" + sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.0.5" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "0ef2b4f97942a16523e51256b799e9aa1843da6c60c55eefbfa9dbc2dcb8331a" + sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1" url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.0.6" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa" + sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4 url: "https://pub.dev" source: hosted - version: "2.0.16" + version: "2.0.18" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: a83ba3607a507758669cfafb03f9de09bf6e6280c14d9b9cb18f013e406dcacd + sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.7" uuid: dependency: "direct main" description: @@ -905,26 +993,34 @@ packages: dependency: transitive description: name: vm_service - sha256: e7fb6c2282f7631712b69c19d1bff82f3767eea33a2321c14fa59ad67ea391c7 + sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 url: "https://pub.dev" source: hosted - version: "9.4.0" + version: "11.10.0" watcher: dependency: transitive description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.0" webkit_inspection_protocol: dependency: transitive description: @@ -937,18 +1033,18 @@ packages: dependency: transitive description: name: win32 - sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "5.0.7" window_manager: dependency: "direct main" description: name: window_manager - sha256: "2b2572442b2a5178642730442dc625ac088244f5827b1f0811371b1b7485eb62" + sha256: "9eef00e393e7f9308309ce9a8b2398c9ee3ca78b50c96e8b4f9873945693ac88" url: "https://pub.dev" source: hosted - version: "0.3.2" + version: "0.3.5" window_size: dependency: "direct main" description: @@ -962,26 +1058,26 @@ packages: dependency: transitive description: name: xdg_directories - sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + sha256: f0c26453a2d47aa4c2570c6a033246a3fc62da2fe23c7ffdd0a7495086dc0247 url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.2" xml: dependency: "direct main" description: name: xml - sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.3.0" yaml: dependency: transitive description: name: yaml - sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" sdks: - dart: ">=2.19.2 <3.0.0" - flutter: ">=3.7.2" + dart: ">=3.1.0-185.0.dev <4.0.0" + flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index d944e010..8f10a90f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,46 +4,51 @@ publish_to: 'none' version: 0.2.0+2 environment: - sdk: '>=2.19.2 <3.0.0' - flutter: '>=3.7.2 <3.10.0' + sdk: '>=3.0.0 <4.0.0' + flutter: '>=3.7.2' dependencies: flutter: sdk: flutter multi_split_view: ^2.4.0 - url_launcher: ^6.1.10 - flutter_riverpod: ^2.1.3 + url_launcher: ^6.1.12 + flutter_riverpod: ^2.3.7 uuid: ^3.0.7 - davi: ^3.2.0 - http: ^0.13.5 + davi: ^3.4.1 + http: ^1.1.0 http_parser: ^4.0.2 - collection: ^1.17.0 - google_fonts: ^4.0.3 + collection: ^1.17.2 + google_fonts: ^5.1.0 highlighter: ^0.1.1 - xml: ^6.2.2 - jinja: ^0.4.2 + xml: ^6.3.0 + jinja: ^0.5.0 window_size: git: url: https://github.com/google/flutter-desktop-embedding.git path: plugins/window_size hive_flutter: ^1.1.0 - lottie: ^2.3.2 + lottie: ^2.6.0 mime_dart: ^3.0.0 - path_provider: ^2.0.14 - window_manager: ^0.3.2 - path: ^1.8.2 - flutter_markdown: ^0.6.14 - markdown: ^7.1.0 + path_provider: ^2.1.0 + window_manager: ^0.3.5 + path: ^1.8.3 + flutter_markdown: ^0.6.17+1 + markdown: ^7.1.1 just_audio: ^0.9.34 - just_audio_mpv: ^0.1.6 + just_audio_mpv: ^0.1.7 just_audio_windows: ^0.2.0 + freezed_annotation: ^2.4.1 + json_annotation: ^4.8.1 dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 - flutter_launcher_icons: ^0.12.0 - test: ^1.22.0 + flutter_lints: ^2.0.2 + flutter_launcher_icons: ^0.13.1 + test: ^1.24.3 + build_runner: ^2.4.6 + freezed: ^2.4.1 + json_serializable: ^6.7.1 flutter: uses-material-design: true diff --git a/test/codegen/dart_http_codegen_test.dart b/test/codegen/dart_http_codegen_test.dart new file mode 100644 index 00000000..fffbf53d --- /dev/null +++ b/test/codegen/dart_http_codegen_test.dart @@ -0,0 +1,505 @@ +import 'package:apidash/codegen/dart/pkg_http.dart'; +import 'package:test/test.dart'; +import '../request_models.dart'; + +void main() { + final dartHttpCodeGen = DartHttpCodeGen(); + + group('GET Request', () { + test('GET 1', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com'); + + final response = await http.get(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelGet1, "https"), expectedCode); + }); + + test('GET 2', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/country/data'); + + var queryParams = { + "code": "US" + }; + uri = uri.replace(queryParameters: queryParams); + + final response = await http.get(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelGet2, "https"), expectedCode); + }); + + test('GET 3', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/country/data?code=US'); + + var queryParams = { + "code": "IND" + }; + var urlQueryParams = Map.from(uri.queryParameters); + urlQueryParams.addAll(queryParams); + uri = uri.replace(queryParameters: urlQueryParams); + + final response = await http.get(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelGet3, "https"), expectedCode); + }); + + test('GET 4', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/humanize/social'); + + var queryParams = { + "num": "8700000", + "digits": "3", + "system": "SS", + "add_space": "true", + "trailing_zeros": "true" + }; + uri = uri.replace(queryParameters: queryParams); + + final response = await http.get(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelGet4, "https"), expectedCode); + }); + + test('GET 5', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.github.com/repos/foss42/apidash'); + + var headers = { + "Authorization": "Bearer XYZ" + }; + + final response = await http.get(uri, + headers: headers); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelGet5, "https"), expectedCode); + }); + + test('GET 6', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.github.com/repos/foss42/apidash'); + + var queryParams = { + "raw": "true" + }; + uri = uri.replace(queryParameters: queryParams); + + var headers = { + "Authorization": "Bearer XYZ" + }; + + final response = await http.get(uri, + headers: headers); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelGet6, "https"), expectedCode); + }); + + test('GET 7', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com'); + + final response = await http.get(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelGet7, "https"), expectedCode); + }); + + test('GET 8', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.github.com/repos/foss42/apidash'); + + var queryParams = { + "raw": "true" + }; + uri = uri.replace(queryParameters: queryParams); + + var headers = { + "Authorization": "Bearer XYZ" + }; + + final response = await http.get(uri, + headers: headers); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelGet8, "https"), expectedCode); + }); + }); + + group('HEAD Request', () { + test('HEAD 1', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com'); + + final response = await http.head(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelHead1, "https"), expectedCode); + }); + + test('HEAD 2', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('http://api.foss42.com'); + + final response = await http.head(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelHead2, "http"), expectedCode); + }); + }); + + group('POST Request', () { + test('POST 1', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/case/lower'); + + String body = r'''{ +"text": "I LOVE Flutter" +}'''; + + var headers = { + "content-type": "text/plain" + }; + + final response = await http.post(uri, + headers: headers, + body: body); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelPost1, "https"), expectedCode); + }); + + test('POST 2', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/case/lower'); + + String body = r'''{ +"text": "I LOVE Flutter" +}'''; + + var headers = { + "content-type": "application/json" + }; + + final response = await http.post(uri, + headers: headers, + body: body); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelPost2, "https"), expectedCode); + }); + + test('POST 3', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://api.foss42.com/case/lower'); + + String body = r'''{ +"text": "I LOVE Flutter" +}'''; + + var headers = { + "Authorization": "Bearer XYZ", + "content-type": "application/json" + }; + + final response = await http.post(uri, + headers: headers, + body: body); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelPost3, "https"), expectedCode); + }); + }); + group('PUT Request', () { + test('PUT 1', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://reqres.in/api/users/2'); + + String body = r'''{ +"name": "morpheus", +"job": "zion resident" +}'''; + + var headers = { + "content-type": "application/json" + }; + + final response = await http.put(uri, + headers: headers, + body: body); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect(dartHttpCodeGen.getCode(requestModelPut1, "https"), expectedCode); + }); + }); + + group('PATCH Request', () { + test('PATCH 1', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://reqres.in/api/users/2'); + + String body = r'''{ +"name": "marfeus", +"job": "accountant" +}'''; + + var headers = { + "content-type": "application/json" + }; + + final response = await http.patch(uri, + headers: headers, + body: body); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect( + dartHttpCodeGen.getCode(requestModelPatch1, "https"), expectedCode); + }); + }); + + group('DELETE Request', () { + test('DELETE 1', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://reqres.in/api/users/2'); + + final response = await http.delete(uri); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect( + dartHttpCodeGen.getCode(requestModelDelete1, "https"), expectedCode); + }); + + test('DELETE 2', () { + const expectedCode = r"""import 'package:http/http.dart' as http; + +void main() async { + var uri = Uri.parse('https://reqres.in/api/users/2'); + + String body = r'''{ +"name": "marfeus", +"job": "accountant" +}'''; + + var headers = { + "content-type": "application/json" + }; + + final response = await http.delete(uri, + headers: headers, + body: body); + + int statusCode = response.statusCode; + if (statusCode >= 200 && statusCode < 300) { + print('Status Code: $statusCode'); + print('Response Body: ${response.body}'); + } + else{ + print('Error Status Code: $statusCode'); + print('Error Response Body: ${response.body}'); + } +} +"""; + expect( + dartHttpCodeGen.getCode(requestModelDelete2, "https"), expectedCode); + }); + }); +} diff --git a/test/codegen/kotlin_okhttp_codegen_test.dart b/test/codegen/kotlin_okhttp_codegen_test.dart index 2582c4ae..2efd1130 100644 --- a/test/codegen/kotlin_okhttp_codegen_test.dart +++ b/test/codegen/kotlin_okhttp_codegen_test.dart @@ -1,19 +1,13 @@ import 'package:apidash/codegen/kotlin/pkg_okhttp.dart'; -import 'package:apidash/models/models.dart' show KVRow, RequestModel; import 'package:test/test.dart'; -import 'package:apidash/consts.dart'; +import '../request_models.dart'; void main() { group('KotlinOkHttpCodeGen', () { final kotlinOkHttpCodeGen = KotlinOkHttpCodeGen(); test('getCode returns valid code for GET request', () { - const requestModel = RequestModel( - url: 'https://jsonplaceholder.typicode.com/todos/1', - method: HTTPVerb.get, - id: '', - ); - const expectedCode = """import okhttp3.MediaType.Companion.toMediaType + const expectedCode = r"""import okhttp3.MediaType.Companion.toMediaType import okhttp3.MultipartBody import okhttp3.OkHttpClient import okhttp3.Request @@ -24,24 +18,17 @@ import java.util.concurrent.TimeUnit val client = OkHttpClient() val request = Request.Builder() - .url("https://jsonplaceholder.typicode.com/todos/1") + .url("https://api.foss42.com") .build() val response = client.newCall(request).execute() println(response.body!!.string()) """; - expect(kotlinOkHttpCodeGen.getCode(requestModel), expectedCode); + expect(kotlinOkHttpCodeGen.getCode(requestModelGet1), expectedCode); }); test('getCode returns valid code for POST request', () { - const requestModel = RequestModel( - url: 'https://jsonplaceholder.typicode.com/posts', - method: HTTPVerb.post, - requestBody: '{"title": "foo","body": "bar","userId": 1}', - requestBodyContentType: ContentType.json, - id: '1', - ); - const expectedCode = """import okhttp3.MediaType.Companion.toMediaType + const expectedCode = r"""import okhttp3.MediaType.Companion.toMediaType import okhttp3.MultipartBody import okhttp3.OkHttpClient import okhttp3.Request @@ -52,27 +39,20 @@ import java.util.concurrent.TimeUnit val client = OkHttpClient() val mediaType = "application/json".toMediaType() -val body = "{\"title\": \"foo\",\"body\": \"bar\",\"userId\": 1}".toRequestBody(mediaType) +val body = "{"text": "IS Upper"}".toRequestBody(mediaType) val request = Request.Builder() - .url("https://jsonplaceholder.typicode.com/posts") + .url("https://api.foss42.com/case/lower") .post(body) .build() val response = client.newCall(request).execute() println(response.body!!.string()) """; - expect(kotlinOkHttpCodeGen.getCode(requestModel), expectedCode); + expect(kotlinOkHttpCodeGen.getCode(requestModelPost1), expectedCode); }); test('getCode returns valid code for DELETE request', () { - const requestModel = RequestModel( - url: 'https://jsonplaceholder.typicode.com/posts/1', - method: HTTPVerb.delete, - requestBody: '{"title": "foo","body": "bar","userId": 1}', - requestBodyContentType: ContentType.json, - id: '1', - ); - const expectedCode = """import okhttp3.MediaType.Companion.toMediaType + const expectedCode = r"""import okhttp3.MediaType.Companion.toMediaType import okhttp3.MultipartBody import okhttp3.OkHttpClient import okhttp3.Request @@ -83,7 +63,7 @@ import java.util.concurrent.TimeUnit val client = OkHttpClient() val mediaType = "application/json".toMediaType() -val body = "{\"title\": \"foo\",\"body\": \"bar\",\"userId\": 1}".toRequestBody(mediaType) +val body = "{"title": "foo","body": "bar","userId": 1}".toRequestBody(mediaType) val request = Request.Builder() .url("https://jsonplaceholder.typicode.com/posts/1") .method("DELETE", body) @@ -92,15 +72,10 @@ val response = client.newCall(request).execute() println(response.body!!.string()) """; - expect(kotlinOkHttpCodeGen.getCode(requestModel), expectedCode); + expect(kotlinOkHttpCodeGen.getCode(requestModelDelete1), expectedCode); }); test('getCode returns valid code for HEAD request', () { - const requestModel = RequestModel( - url: 'https://jsonplaceholder.typicode.com/posts/1', - method: HTTPVerb.head, - id: '1', - ); const expectedCode = """import okhttp3.MediaType.Companion.toMediaType import okhttp3.MultipartBody import okhttp3.OkHttpClient @@ -119,24 +94,12 @@ val response = client.newCall(request).execute() println(response.body!!.string()) """; - expect(kotlinOkHttpCodeGen.getCode(requestModel), expectedCode); + expect(kotlinOkHttpCodeGen.getCode(requestModelHead1), expectedCode); }); test( 'getCode returns valid code for requests with headers and query parameters', () { - const requestModel = RequestModel( - url: 'https://jsonplaceholder.typicode.com/posts', - method: HTTPVerb.get, - requestParams: [ - KVRow('userId', 1), - ], - requestHeaders: [ - KVRow('Custom-Header-1', 'Value-1'), - KVRow('Custom-Header-2', 'Value-2') - ], - id: '1', - ); const expectedCode = """import okhttp3.MediaType.Companion.toMediaType import okhttp3.MultipartBody import okhttp3.OkHttpClient @@ -157,7 +120,7 @@ val response = client.newCall(request).execute() println(response.body!!.string()) """; - expect(kotlinOkHttpCodeGen.getCode(requestModel), expectedCode); + expect(kotlinOkHttpCodeGen.getCode(requestModelGet2), expectedCode); }); }); } diff --git a/test/models/kvrow_model_test.dart b/test/models/kvrow_model_test.dart index f6f5b3a6..44093da5 100644 --- a/test/models/kvrow_model_test.dart +++ b/test/models/kvrow_model_test.dart @@ -1,17 +1,17 @@ import 'package:test/test.dart'; -import 'package:apidash/models/kvrow_model.dart'; +import 'package:apidash/models/name_value_model.dart'; void main() { - KVRow kvRow1 = const KVRow("harry", 23); + const kvRow1 = NameValueModel(name: "harry", value: 23); String kvRow1Expected = "{harry: 23}"; test('Testing toString()', () { expect(kvRow1.toString(), kvRow1Expected); }); - KVRow kvRow2Expected = const KVRow("winter", "26"); + const kvRow2Expected = NameValueModel(name: "winter", value: "26"); test('Testing copyWith()', () { - expect(kvRow1.copyWith(k: "winter", v: "26"), kvRow2Expected); + expect(kvRow1.copyWith(name: "winter", value: "26"), kvRow2Expected); }); test('Testing hashcode', () { diff --git a/test/models/request_model_test.dart b/test/models/request_model_test.dart index c70cb8ac..4d08da65 100644 --- a/test/models/request_model_test.dart +++ b/test/models/request_model_test.dart @@ -55,8 +55,9 @@ void main() { url: 'api.foss42.com/case/lower', name: 'foss42 api', requestHeaders: const [ - KVRow('content-length', '18'), - KVRow('content-type', 'application/json; charset=utf-8') + NameValueModel(name: 'content-length', value: '18'), + NameValueModel( + name: 'content-type', value: 'application/json; charset=utf-8') ], requestBodyContentType: ContentType.json, requestBody: '''{ @@ -71,8 +72,9 @@ void main() { url: 'api.foss42.com/case/lower', name: 'foss42 api', requestHeaders: [ - KVRow('content-length', '18'), - KVRow('content-type', 'application/json; charset=utf-8') + NameValueModel(name: 'content-length', value: '18'), + NameValueModel( + name: 'content-type', value: 'application/json; charset=utf-8') ], requestBodyContentType: ContentType.json, requestBody: '''{ diff --git a/test/request_models.dart b/test/request_models.dart new file mode 100644 index 00000000..73090e21 --- /dev/null +++ b/test/request_models.dart @@ -0,0 +1,182 @@ +import 'package:apidash/models/models.dart' show NameValueModel, RequestModel; +import 'package:apidash/consts.dart'; + +/// Basic GET request model +const requestModelGet1 = RequestModel( + id: 'get1', + url: 'https://api.foss42.com', + method: HTTPVerb.get, +); + +/// GET request model with query params +const requestModelGet2 = RequestModel( + id: 'get2', + url: 'https://api.foss42.com/country/data', + method: HTTPVerb.get, + requestParams: [ + NameValueModel(name: 'code', value: 'US'), + ], +); + +/// GET request model with override query params +const requestModelGet3 = RequestModel( + id: 'get3', + url: 'https://api.foss42.com/country/data?code=US', + method: HTTPVerb.get, + requestParams: [ + NameValueModel(name: 'code', value: 'IND'), + ], +); + +/// GET request model with different types of query params +const requestModelGet4 = RequestModel( + id: 'get4', + url: 'https://api.foss42.com/humanize/social', + method: HTTPVerb.get, + requestParams: [ + NameValueModel(name: 'num', value: '8700000'), + NameValueModel(name: 'digits', value: '3'), + NameValueModel(name: 'system', value: 'SS'), + NameValueModel(name: 'add_space', value: 'true'), + NameValueModel(name: 'trailing_zeros', value: 'true'), + ], +); + +/// GET request model with headers +const requestModelGet5 = RequestModel( + id: 'get5', + url: 'https://api.github.com/repos/foss42/apidash', + method: HTTPVerb.get, + requestHeaders: [ + NameValueModel(name: 'Authorization', value: 'Bearer XYZ'), + ], +); + +/// GET request model with headers & query params +const requestModelGet6 = RequestModel( + id: 'get6', + url: 'https://api.github.com/repos/foss42/apidash', + method: HTTPVerb.get, + requestHeaders: [ + NameValueModel(name: 'Authorization', value: 'Bearer XYZ'), + ], + requestParams: [ + NameValueModel(name: 'raw', value: 'true'), + ], +); + +/// GET request model with body +const requestModelGet7 = RequestModel( + id: 'get7', + url: 'https://api.foss42.com', + method: HTTPVerb.get, + requestBodyContentType: ContentType.text, + requestBody: + 'This is a random text which should not be attached with a GET request', +); + +/// GET request model with empty header & query param name +const requestModelGet8 = RequestModel( + id: 'get8', + url: 'https://api.github.com/repos/foss42/apidash', + method: HTTPVerb.get, + requestHeaders: [ + NameValueModel(name: 'Authorization', value: 'Bearer XYZ'), + NameValueModel(name: '', value: 'Bearer XYZ'), + ], + requestParams: [ + NameValueModel(name: 'raw', value: 'true'), + NameValueModel(name: '', value: 'true'), + ], +); + +/// Basic HEAD request model +const requestModelHead1 = RequestModel( + id: 'head1', + url: 'https://api.foss42.com', + method: HTTPVerb.head, +); + +/// Without URI Scheme (pass default as http) +const requestModelHead2 = RequestModel( + id: 'head2', + url: 'api.foss42.com', + method: HTTPVerb.head, +); + +/// Basic POST request model (txt body) +const requestModelPost1 = RequestModel( + id: 'post1', + url: 'https://api.foss42.com/case/lower', + method: HTTPVerb.post, + requestBody: r"""{ +"text": "I LOVE Flutter" +}""", + requestBodyContentType: ContentType.text); + +/// POST request model with JSON body +const requestModelPost2 = RequestModel( + id: 'post2', + url: 'https://api.foss42.com/case/lower', + method: HTTPVerb.post, + requestBody: r"""{ +"text": "I LOVE Flutter" +}""", +); + +/// POST request model with headers +const requestModelPost3 = RequestModel( + id: 'post3', + url: 'https://api.foss42.com/case/lower', + method: HTTPVerb.post, + requestBody: r"""{ +"text": "I LOVE Flutter" +}""", + requestBodyContentType: ContentType.json, + requestHeaders: [ + NameValueModel(name: 'Authorization', value: 'Bearer XYZ'), + ], +); + +/// PUT request model +const requestModelPut1 = RequestModel( + id: 'put1', + url: 'https://reqres.in/api/users/2', + method: HTTPVerb.put, + requestBody: r"""{ +"name": "morpheus", +"job": "zion resident" +}""", + requestBodyContentType: ContentType.json, +); + +/// PATCH request model +const requestModelPatch1 = RequestModel( + id: 'patch1', + url: 'https://reqres.in/api/users/2', + method: HTTPVerb.patch, + requestBody: r"""{ +"name": "marfeus", +"job": "accountant" +}""", + requestBodyContentType: ContentType.json, +); + +/// Basic DELETE request model +const requestModelDelete1 = RequestModel( + id: 'delete1', + url: 'https://reqres.in/api/users/2', + method: HTTPVerb.delete, +); + +/// Basic DELETE with body +const requestModelDelete2 = RequestModel( + id: 'delete1', + url: 'https://reqres.in/api/users/2', + method: HTTPVerb.delete, + requestBody: r"""{ +"name": "marfeus", +"job": "accountant" +}""", + requestBodyContentType: ContentType.json, +); diff --git a/test/test_utilities.dart b/test/test_utilities.dart index 076e7bca..3f5c3fc1 100644 --- a/test/test_utilities.dart +++ b/test/test_utilities.dart @@ -1,15 +1,19 @@ import 'dart:math'; -const _chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890'; -Random _rnd = Random(); +class RandomStringGenerator { + static const _chars = + 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890'; + static Random rnd = Random(); -String getRandomString(int length) => String.fromCharCodes(Iterable.generate( - length, (_) => _chars.codeUnitAt(_rnd.nextInt(_chars.length)))); + static String getRandomString(int length) => + String.fromCharCodes(Iterable.generate( + length, (_) => _chars.codeUnitAt(rnd.nextInt(_chars.length)))); -String getRandomStringLines(int lines, int length) { - List result = []; - for (var i = 0; i < lines; i++) { - result.add(getRandomString(length)); + static String getRandomStringLines(int lines, int length) { + List result = []; + for (var i = 0; i < lines; i++) { + result.add(getRandomString(length)); + } + return result.join('\n'); } - return result.join('\n'); } diff --git a/test/utils/convert_utils_test.dart b/test/utils/convert_utils_test.dart index 57ae8b51..26be2c10 100644 --- a/test/utils/convert_utils_test.dart +++ b/test/utils/convert_utils_test.dart @@ -1,6 +1,6 @@ import 'package:test/test.dart'; import 'package:apidash/utils/convert_utils.dart'; -import 'package:apidash/models/kvrow_model.dart'; +import 'package:apidash/models/name_value_model.dart'; void main() { group("Testing humanizeDuration function", () { @@ -73,18 +73,18 @@ void main() { expect(rowsToMap(null), null); }); test('Testing for string KVRow values', () { - KVRow kvRow1 = const KVRow("code", "IN"); + const kvRow1 = NameValueModel(name: "code", value: "IN"); expect(rowsToMap([kvRow1]), {"code": "IN"}); }); test('Testing when header is True', () { - KVRow kvRow2 = const KVRow("Text", "ABC"); + const kvRow2 = NameValueModel(name: "Text", value: "ABC"); expect(rowsToMap([kvRow2], isHeader: true), {"text": "ABC"}); }); test('Testing when header is false and key is in upper case', () { - List kvRow3 = const [ - KVRow("TEXT", "ABC"), - KVRow("version", 0.1), - KVRow("month", 4) + const kvRow3 = [ + NameValueModel(name: "TEXT", value: "ABC"), + NameValueModel(name: "version", value: 0.1), + NameValueModel(name: "month", value: 4), ]; expect( rowsToMap(kvRow3), {"TEXT": "ABC", "version": "0.1", "month": "4"}); @@ -97,10 +97,10 @@ void main() { }); test('Testing with a map value', () { Map value1 = {"text": "abc", "lang": "eng", "code": "1"}; - List result1Expected = const [ - KVRow("text", "abc"), - KVRow("lang", "eng"), - KVRow("code", "1") + const result1Expected = [ + NameValueModel(name: "text", value: "abc"), + NameValueModel(name: "lang", value: "eng"), + NameValueModel(name: "code", value: "1") ]; expect(mapToRows(value1), result1Expected); }); diff --git a/test/utils/file_utils_test.dart b/test/utils/file_utils_test.dart new file mode 100644 index 00000000..fef80ace --- /dev/null +++ b/test/utils/file_utils_test.dart @@ -0,0 +1,17 @@ +import 'package:test/test.dart'; +import 'package:apidash/utils/file_utils.dart'; + +void main() { + group( + "Testing x function", + () { + /*test('Test case 2', () { + expect(showButtonLabelsInViewCodePane(350), false); + }); + + test('Test case 3', () { + expect(showButtonLabelsInViewCodePane(450), true); + });*/ + }, + ); +} diff --git a/test/utils/http_utils_test.dart b/test/utils/http_utils_test.dart index 80d63103..1fcd96a2 100644 --- a/test/utils/http_utils_test.dart +++ b/test/utils/http_utils_test.dart @@ -1,7 +1,7 @@ import 'package:test/test.dart'; import 'package:http_parser/http_parser.dart'; import 'package:apidash/utils/http_utils.dart'; -import 'package:apidash/models/kvrow_model.dart'; +import 'package:apidash/models/name_value_model.dart'; import 'package:apidash/consts.dart'; import '../test_utilities.dart'; @@ -156,74 +156,74 @@ void main() { path: 'guides/libraries/library-tour', fragment: 'numbers'); String uriScheme1Expected = 'https'; - expect(getUriScheme(uri1), (uriScheme1Expected,true)); + expect(getUriScheme(uri1), (uriScheme1Expected, true)); }); test('Testing getUriScheme for mailto scheme value', () { Uri uri2 = Uri(scheme: 'mailto'); String uriScheme2Expected = 'mailto'; - expect(getUriScheme(uri2), (uriScheme2Expected,false)); + expect(getUriScheme(uri2), (uriScheme2Expected, false)); }); test('Testing getUriScheme for empty scheme value', () { - Uri uri3 = Uri( - scheme: ''); - expect(getUriScheme(uri3), (null,false)); + Uri uri3 = Uri(scheme: ''); + expect(getUriScheme(uri3), (null, false)); }); test('Testing getUriScheme for null scheme value', () { - Uri uri4 = Uri( - scheme: null); - expect(getUriScheme(uri4), (null,false)); + Uri uri4 = Uri(scheme: null); + expect(getUriScheme(uri4), (null, false)); }); }); group("Testing getValidRequestUri", () { test('Testing getValidRequestUri for normal values', () { String url1 = "https://api.foss42.com/country/data"; - KVRow kvRow1 = const KVRow("code", "US"); + const kvRow1 = NameValueModel(name: "code", value: "US"); Uri uri1Expected = Uri( scheme: 'https', host: 'api.foss42.com', path: 'country/data', - queryParameters: {'code':'US'}); + queryParameters: {'code': 'US'}); expect(getValidRequestUri(url1, [kvRow1]), (uri1Expected, null)); }); test('Testing getValidRequestUri for null url value', () { - KVRow kvRow2 = const KVRow("code", "US"); + const kvRow2 = NameValueModel(name: "code", value: "US"); expect(getValidRequestUri(null, [kvRow2]), (null, "URL is missing!")); }); test('Testing getValidRequestUri for empty url value', () { - KVRow kvRow3 = const KVRow("", ""); + const kvRow3 = NameValueModel(name: "", value: ""); expect(getValidRequestUri("", [kvRow3]), (null, "URL is missing!")); }); test('Testing getValidRequestUri when https is not provided in url', () { String url4 = "api.foss42.com/country/data"; - KVRow kvRow4 = const KVRow("code", "US"); + const kvRow4 = NameValueModel(name: "code", value: "US"); Uri uri4Expected = Uri( scheme: 'https', host: 'api.foss42.com', path: 'country/data', - queryParameters: {'code':'US'}); + queryParameters: {'code': 'US'}); expect(getValidRequestUri(url4, [kvRow4]), (uri4Expected, null)); }); test('Testing getValidRequestUri when url has fragment', () { String url5 = "https://dart.dev/guides/libraries/library-tour#numbers"; Uri uri5Expected = Uri( - scheme: 'https', - host: 'dart.dev', - path: '/guides/libraries/library-tour'); + scheme: 'https', + host: 'dart.dev', + path: '/guides/libraries/library-tour'); expect(getValidRequestUri(url5, null), (uri5Expected, null)); }); test('Testing getValidRequestUri when uri scheme is not supported', () { String url5 = "mailto:someone@example.com"; - expect(getValidRequestUri(url5, null), (null, "Unsupported URL Scheme (mailto)")); + expect(getValidRequestUri(url5, null), + (null, "Unsupported URL Scheme (mailto)")); }); - test('Testing getValidRequestUri when query params in both url and kvrow', () { + test('Testing getValidRequestUri when query params in both url and kvrow', + () { String url6 = "api.foss42.com/country/data?code=IND"; - KVRow kvRow6 = const KVRow("code", "US"); + const kvRow6 = NameValueModel(name: "code", value: "US"); Uri uri6Expected = Uri( scheme: 'https', host: 'api.foss42.com', path: 'country/data', - queryParameters: {'code':'US'}); + queryParameters: {'code': 'US'}); expect(getValidRequestUri(url6, [kvRow6]), (uri6Expected, null)); }); test('Testing getValidRequestUri when kvrow is null', () { @@ -232,7 +232,7 @@ void main() { scheme: 'https', host: 'api.foss42.com', path: 'country/data', - queryParameters: {'code':'US'}); + queryParameters: {'code': 'US'}); expect(getValidRequestUri(url7, null), (uri7Expected, null)); }); }); @@ -241,72 +241,78 @@ void main() { test('Testing getResponseBodyViewOptions for application/json', () { MediaType mediaType1 = MediaType("application", "json"); var result1 = getResponseBodyViewOptions(mediaType1); - expect(result1.$0,kCodeRawBodyViewOptions); - expect(result1.$1, "json"); + expect(result1.$1, kCodeRawBodyViewOptions); + expect(result1.$2, "json"); }); test('Testing getResponseBodyViewOptions for application/xml', () { MediaType mediaType2 = MediaType("application", "xml"); var result2 = getResponseBodyViewOptions(mediaType2); - expect(result2.$0, kCodeRawBodyViewOptions); - expect(result2.$1,"xml"); + expect(result2.$1, kCodeRawBodyViewOptions); + expect(result2.$2, "xml"); }); - test('Testing getResponseBodyViewOptions for message/news a format currently not supported', () { + test( + 'Testing getResponseBodyViewOptions for message/news a format currently not supported', + () { MediaType mediaType3 = MediaType("message", "news"); var result3 = getResponseBodyViewOptions(mediaType3); - expect(result3.$0,kNoBodyViewOptions); - expect(result3.$1,null); + expect(result3.$1, kNoBodyViewOptions); + expect(result3.$2, null); }); - test('Testing getResponseBodyViewOptions for application/calendar+json', () { + test('Testing getResponseBodyViewOptions for application/calendar+json', + () { MediaType mediaType4 = MediaType("application", "calendar+json"); var result4 = getResponseBodyViewOptions(mediaType4); - expect(result4.$0,kCodeRawBodyViewOptions); - expect(result4.$1, "json"); + expect(result4.$1, kCodeRawBodyViewOptions); + expect(result4.$2, "json"); }); test('Testing getResponseBodyViewOptions for image/svg+xml', () { MediaType mediaType5 = MediaType("image", "svg+xml"); var result5 = getResponseBodyViewOptions(mediaType5); - expect(result5.$0,kCodeRawBodyViewOptions); - expect(result5.$1, "xml"); + expect(result5.$1, kCodeRawBodyViewOptions); + expect(result5.$2, "xml"); }); test('Testing getResponseBodyViewOptions for application/xhtml+xml', () { MediaType mediaType6 = MediaType("application", "xhtml+xml"); var result6 = getResponseBodyViewOptions(mediaType6); - expect(result6.$0,kCodeRawBodyViewOptions); - expect(result6.$1, "xml"); + expect(result6.$1, kCodeRawBodyViewOptions); + expect(result6.$2, "xml"); }); - test('Testing getResponseBodyViewOptions for application/xml-external-parsed-entity', () { - MediaType mediaType7 = MediaType("application", "xml-external-parsed-entity"); + test( + 'Testing getResponseBodyViewOptions for application/xml-external-parsed-entity', + () { + MediaType mediaType7 = + MediaType("application", "xml-external-parsed-entity"); var result7 = getResponseBodyViewOptions(mediaType7); - expect(result7.$0,kCodeRawBodyViewOptions); - expect(result7.$1, "xml"); + expect(result7.$1, kCodeRawBodyViewOptions); + expect(result7.$2, "xml"); }); test('Testing getResponseBodyViewOptions for text/html', () { MediaType mediaType8 = MediaType("text", "html"); var result8 = getResponseBodyViewOptions(mediaType8); - expect(result8.$0,kCodeRawBodyViewOptions); - expect(result8.$1, "xml"); + expect(result8.$1, kCodeRawBodyViewOptions); + expect(result8.$2, "xml"); }); test('Testing getResponseBodyViewOptions for application/pdf', () { MediaType mediaType9 = MediaType("application", "pdf"); var result9 = getResponseBodyViewOptions(mediaType9); - expect(result9.$0,kNoBodyViewOptions); - expect(result9.$1, "pdf"); + expect(result9.$1, kNoBodyViewOptions); + expect(result9.$2, "pdf"); }); - test('Testing getResponseBodyViewOptions for text/calendar', () { + test('Testing getResponseBodyViewOptions for text/calendar', () { MediaType mediaType10 = MediaType("text", "calendar"); var result10 = getResponseBodyViewOptions(mediaType10); - expect(result10.$0,kRawBodyViewOptions); - expect(result10.$1, "calendar"); + expect(result10.$1, kRawBodyViewOptions); + expect(result10.$2, "calendar"); }); }); group("Testing formatBody", () { test('Testing formatBody for null values', () { - expect(formatBody(null, null),null); + expect(formatBody(null, null), null); }); test('Testing formatBody for null body values', () { MediaType mediaType1 = MediaType("application", "xml"); - expect(formatBody(null, mediaType1),null); + expect(formatBody(null, mediaType1), null); }); test('Testing formatBody for null MediaType values', () { String body1 = ''' @@ -314,7 +320,7 @@ void main() { "text":"The Chosen One"; } '''; - expect(formatBody(body1, null),null); + expect(formatBody(body1, null), null); }); test('Testing formatBody for json subtype values', () { String body2 = '''{"data":{"area":9831510.0,"population":331893745}}'''; @@ -325,7 +331,7 @@ void main() { "population": 331893745 } }'''; - expect(formatBody(body2, mediaType2),result2Expected); + expect(formatBody(body2, mediaType2), result2Expected); }); test('Testing formatBody for xml subtype values', () { String body3 = ''' @@ -347,28 +353,32 @@ void main() { 650 '''; - expect(formatBody(body3, mediaType3),result3Expected); + expect(formatBody(body3, mediaType3), result3Expected); }); group("Testing formatBody for html", () { MediaType mediaTypeHtml = MediaType("text", "html"); test('Testing formatBody for html subtype values', () { - String body4 = ''' + String body4 = '''

My First Heading

My first paragraph.

-'''; - expect(formatBody(body4, mediaTypeHtml),body4); +'''; + expect(formatBody(body4, mediaTypeHtml), body4); + }); + + test('Testing formatBody for html subtype values with random values', () { + String body5 = + '''${RandomStringGenerator.getRandomStringLines(100, 10000)}'''; + expect(formatBody(body5, mediaTypeHtml), null); + }); + test( + 'Testing formatBody for html subtype values with random values within limit', + () { + String body6 = + '''${RandomStringGenerator.getRandomStringLines(100, 190)}'''; + expect(formatBody(body6, mediaTypeHtml), body6); + }); }); - - test('Testing formatBody for html subtype values with random values', () { - String body5 = '''${getRandomStringLines(100, 10000)}'''; - expect(formatBody(body5, mediaTypeHtml),null); - }); - test('Testing formatBody for html subtype values with random values within limit', () { - String body6 = '''${getRandomStringLines(100, 190)}'''; - expect(formatBody(body6, mediaTypeHtml),body6); - }); - }); }); } diff --git a/test/utils/window_utils_test.dart b/test/utils/window_utils_test.dart new file mode 100644 index 00000000..55034a1d --- /dev/null +++ b/test/utils/window_utils_test.dart @@ -0,0 +1,62 @@ +import 'package:test/test.dart'; +import 'package:apidash/utils/window_utils.dart'; + +void main() { + group( + "Testing showButtonLabelsInBodySuccess function", + () { + test('Test case 1 options 0', () { + expect(showButtonLabelsInBodySuccess(0, 300), true); + }); + + test('Test case 2 options 0', () { + expect(showButtonLabelsInBodySuccess(0, 500), true); + }); + + test('Test case 1 options 1', () { + expect(showButtonLabelsInBodySuccess(1, 250), false); + }); + + test('Test case 2 options 1', () { + expect(showButtonLabelsInBodySuccess(1, 350), true); + }); + + test('Test case 1 options 2', () { + expect(showButtonLabelsInBodySuccess(2, 250), false); + }); + + test('Test case 2 options 2', () { + expect(showButtonLabelsInBodySuccess(2, 350), false); + }); + + test('Test case 3 options 2', () { + expect(showButtonLabelsInBodySuccess(2, 450), true); + }); + + test('Test case 1 options 3', () { + expect(showButtonLabelsInBodySuccess(3, 350), false); + }); + + test('Test case 2 options 3', () { + expect(showButtonLabelsInBodySuccess(3, 450), false); + }); + + test('Test case 3 options 3', () { + expect(showButtonLabelsInBodySuccess(3, 550), true); + }); + }, + ); + + group( + "Testing showButtonLabelsInViewCodePane function", + () { + test('Test case 2', () { + expect(showButtonLabelsInViewCodePane(350), false); + }); + + test('Test case 3', () { + expect(showButtonLabelsInViewCodePane(450), true); + }); + }, + ); +} diff --git a/test/widget_test.dart b/test/widget_test.dart index c0e5cab0..ab73b3a2 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -1,31 +1 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:apidash/app.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:apidash/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const DashApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} +void main() {} diff --git a/test/widgets/code_previewer_test.dart b/test/widgets/code_previewer_test.dart index c57478c9..6fd77b4f 100644 --- a/test/widgets/code_previewer_test.dart +++ b/test/widgets/code_previewer_test.dart @@ -50,7 +50,7 @@ void main() async { }); testWidgets('Testing for code previewer when code is of 1000 lines', (tester) async { - String codeLines = getRandomStringLines(1000, 20); + String codeLines = RandomStringGenerator.getRandomStringLines(1000, 20); await tester.pumpWidget( MaterialApp( title: 'Code Previewer', diff --git a/test/widgets/codegen_previewer_test.dart b/test/widgets/codegen_previewer_test.dart index 4b51aa8a..665f5a0c 100644 --- a/test/widgets/codegen_previewer_test.dart +++ b/test/widgets/codegen_previewer_test.dart @@ -69,7 +69,18 @@ void main() async { ); await tester.pumpAndSettle(); - expect(find.text('Code'), findsOneWidget); + expect(find.byType(DropdownButton), findsOneWidget); + expect( + (tester.widget(find.byType(DropdownButton)) + as DropdownButton) + .value, + equals(CodegenLanguage.dartHttp)); + + await tester.tap(find.text('Dart (http)')); + await tester.pump(); + await tester.pump(const Duration(seconds: 1)); + + expect(find.text('Kotlin (OkHttp)'), findsWidgets); expect(find.textContaining('Error Status Code', findRichText: true), findsOneWidget); @@ -97,7 +108,7 @@ void main() async { ); await tester.pumpAndSettle(); - expect(find.text('Code'), findsOneWidget); + expect(find.text('Dart (http)'), findsOneWidget); expect(find.textContaining('Error Status Code', findRichText: true), findsOneWidget); diff --git a/test/widgets/response_widgets_test.dart b/test/widgets/response_widgets_test.dart index 2822e0a8..632d29bd 100644 --- a/test/widgets/response_widgets_test.dart +++ b/test/widgets/response_widgets_test.dart @@ -204,8 +204,9 @@ void main() { url: 'api.foss42.com/case/lower', name: 'foss42 api', requestHeaders: [ - KVRow('content-length', '18'), - KVRow('content-type', 'application/json; charset=utf-8') + NameValueModel(name: 'content-length', value: '18'), + NameValueModel( + name: 'content-type', value: 'application/json; charset=utf-8') ], requestBodyContentType: ContentType.json, requestBody: '''{ diff --git a/test/widgets/splitviews_test.dart b/test/widgets/splitviews_test.dart index 108947cb..3e9d8d59 100644 --- a/test/widgets/splitviews_test.dart +++ b/test/widgets/splitviews_test.dart @@ -6,12 +6,12 @@ import 'package:multi_split_view/multi_split_view.dart'; void main() { testWidgets('Testing for Dashboard Splitview', (tester) async { await tester.pumpWidget( - MaterialApp( + const MaterialApp( title: 'Dashboard Splitview', home: Scaffold( body: DashboardSplitView( - sidebarWidget: Column(children: const [Text("Hello")]), - mainWidget: Column(children: const [Text("World")]), + sidebarWidget: Column(children: [Text("Hello")]), + mainWidget: Column(children: [Text("World")]), ), ), ), @@ -23,12 +23,12 @@ void main() { }); testWidgets('Testing for Equal SplitView', (tester) async { await tester.pumpWidget( - MaterialApp( + const MaterialApp( title: 'Equal SplitView', home: Scaffold( body: EqualSplitView( - leftWidget: Column(children: const [Text("Hello equal")]), - rightWidget: Column(children: const [Text("World equal")]), + leftWidget: Column(children: [Text("Hello equal")]), + rightWidget: Column(children: [Text("World equal")]), ), ), ), diff --git a/test/widgets/textfields_test.dart b/test/widgets/textfields_test.dart index 632b84e0..b50bf4bd 100644 --- a/test/widgets/textfields_test.dart +++ b/test/widgets/textfields_test.dart @@ -10,8 +10,8 @@ void main() { MaterialApp( title: 'URL Field', theme: kThemeDataDark, - home: Scaffold( - body: Column(children: const [URLField(activeId: '2')]), + home: const Scaffold( + body: Column(children: [URLField(activeId: '2')]), ), ), ); @@ -30,9 +30,9 @@ void main() { MaterialApp( title: 'CellField', theme: kThemeDataLight, - home: Scaffold( + home: const Scaffold( body: Column( - children: const [ + children: [ CellField( keyId: "4", hintText: "Passing some hint text",