mirror of
https://github.com/foss42/apidash.git
synced 2025-08-06 13:51:20 +08:00
Merge branch 'main' into main
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -49,8 +49,10 @@ linux/
|
||||
macos/
|
||||
windows/
|
||||
web/
|
||||
ios/
|
||||
.vscode/*
|
||||
icons/
|
||||
coverage/*
|
||||
installers/*
|
||||
.metadata
|
||||
.fvm/
|
||||
|
@ -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/<user>/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 <file_path>.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).
|
||||
|
@ -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.
|
||||
|
||||
|
20
README.md
20
README.md
@ -23,21 +23,21 @@ API Dash can be downloaded from the links below:
|
||||
<tr>
|
||||
<td>macOS</td>
|
||||
<td><code>.dmg</code></td>
|
||||
<td><a href="https://github.com/foss42/api-dash/blob/main/INSTALLATION.md#macos">Link</a></td>
|
||||
<td><a href="https://github.com/foss42/apidash/blob/main/INSTALLATION.md#macos">Link</a></td>
|
||||
<td>Apple Silicon & Intel</td>
|
||||
<td><a href="https://bit.ly/44wmazf">Link</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Windows</td>
|
||||
<td><code>.exe</code></td>
|
||||
<td><a href="https://github.com/foss42/api-dash/blob/main/INSTALLATION.md#windows">Link</a></td>
|
||||
<td><a href="https://github.com/foss42/apidash/blob/main/INSTALLATION.md#windows">Link</a></td>
|
||||
<td>64-bit</td>
|
||||
<td><a href="https://bit.ly/424ExKb">Link</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=4>Linux</td>
|
||||
<td rowspan=2><code>.deb</code></td>
|
||||
<td rowspan=2><a href="https://github.com/foss42/api-dash/blob/main/INSTALLATION.md#debian-based-linux-distributions-debian-ubuntu-linux-mint-etc">Link</a></td>
|
||||
<td rowspan=2><a href="https://github.com/foss42/apidash/blob/main/INSTALLATION.md#debian-based-linux-distributions-debian-ubuntu-linux-mint-etc">Link</a></td>
|
||||
<td>amd64</td>
|
||||
<td><a href="https://bit.ly/44sWPq2">Link</a></td>
|
||||
</tr>
|
||||
@ -47,7 +47,7 @@ API Dash can be downloaded from the links below:
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=2><code>.rpm</code></td>
|
||||
<td rowspan=2><a href="https://github.com/foss42/api-dash/blob/main/INSTALLATION.md#red-hat-based-linux-distributions-fedora-rocky-almalinux-centos-rhel-etc">Link</a></td>
|
||||
<td rowspan=2><a href="https://github.com/foss42/apidash/blob/main/INSTALLATION.md#red-hat-based-linux-distributions-fedora-rocky-almalinux-centos-rhel-etc">Link</a></td>
|
||||
<td>x86_64</td>
|
||||
<td><a href="https://bit.ly/417gWHe">Link</a></td>
|
||||
</tr>
|
||||
@ -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).
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(' ');
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
@ -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';
|
||||
|
17
lib/models/name_value_model.dart
Normal file
17
lib/models/name_value_model.dart
Normal file
@ -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<String, Object?> json) =>
|
||||
_$NameValueModelFromJson(json);
|
||||
}
|
181
lib/models/name_value_model.freezed.dart
Normal file
181
lib/models/name_value_model.freezed.dart
Normal file
@ -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>(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<String, dynamic> json) {
|
||||
return _NameValueModel.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$NameValueModel {
|
||||
String get name => throw _privateConstructorUsedError;
|
||||
dynamic get value => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$NameValueModelCopyWith<NameValueModel> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> json) =
|
||||
_$_NameValueModel.fromJson;
|
||||
|
||||
@override
|
||||
String get name;
|
||||
@override
|
||||
dynamic get value;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$_NameValueModelCopyWith<_$_NameValueModel> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
19
lib/models/name_value_model.g.dart
Normal file
19
lib/models/name_value_model.g.dart
Normal file
@ -0,0 +1,19 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'name_value_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$_NameValueModel _$$_NameValueModelFromJson(Map<String, dynamic> json) =>
|
||||
_$_NameValueModel(
|
||||
name: json['name'] as String,
|
||||
value: json['value'],
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$_NameValueModelToJson(_$_NameValueModel instance) =>
|
||||
<String, dynamic>{
|
||||
'name': instance.name,
|
||||
'value': instance.value,
|
||||
};
|
@ -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<KVRow>? requestHeaders;
|
||||
final List<KVRow>? requestParams;
|
||||
final List<NameValueModel>? requestHeaders;
|
||||
final List<NameValueModel>? requestParams;
|
||||
final ContentType requestBodyContentType;
|
||||
final String? requestBody;
|
||||
final int? responseStatus;
|
||||
@ -59,8 +59,8 @@ class RequestModel {
|
||||
String? name,
|
||||
String? description,
|
||||
int? requestTabIndex,
|
||||
List<KVRow>? requestHeaders,
|
||||
List<KVRow>? requestParams,
|
||||
List<NameValueModel>? requestHeaders,
|
||||
List<NameValueModel>? requestParams,
|
||||
ContentType? requestBodyContentType,
|
||||
String? requestBody,
|
||||
int? responseStatus,
|
||||
|
@ -96,8 +96,8 @@ class CollectionStateNotifier extends StateNotifier<List<RequestModel>?> {
|
||||
String? name,
|
||||
String? description,
|
||||
int? requestTabIndex,
|
||||
List<KVRow>? requestHeaders,
|
||||
List<KVRow>? requestParams,
|
||||
List<NameValueModel>? requestHeaders,
|
||||
List<NameValueModel>? requestParams,
|
||||
ContentType? requestBodyContentType,
|
||||
String? requestBody,
|
||||
int? responseStatus,
|
||||
@ -132,17 +132,17 @@ class CollectionStateNotifier extends StateNotifier<List<RequestModel>?> {
|
||||
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<List<RequestModel>?> {
|
||||
await hiveHandler.removeUnused();
|
||||
ref.read(saveDataStateProvider.notifier).update((state) => false);
|
||||
}
|
||||
|
||||
Map<String, dynamic> exportData() {
|
||||
return {
|
||||
"data": state!.map((e) => e.toJson(includeResponse: false)).toList()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +25,11 @@ class _EditRequestBodyState extends ConsumerState<EditRequestBody> {
|
||||
margin: kPt5o10,
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: kHeaderHeight,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: const [
|
||||
children: [
|
||||
Text(
|
||||
"Select Content Type:",
|
||||
),
|
||||
|
@ -15,7 +15,7 @@ class EditRequestHeaders extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
late List<KVRow> rows;
|
||||
late List<NameValueModel> rows;
|
||||
final random = Random.secure();
|
||||
late int seed;
|
||||
|
||||
@ -37,9 +37,11 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
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<KVRow> model = DaviModel<KVRow>(
|
||||
DaviModel<NameValueModel> model = DaviModel<NameValueModel>(
|
||||
rows: rows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
@ -49,10 +51,10 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
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<EditRequestHeaders> {
|
||||
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<EditRequestHeaders> {
|
||||
? 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<EditRequestHeaders> {
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: kTableThemeData,
|
||||
child: Davi<KVRow>(model),
|
||||
child: Davi<NameValueModel>(model),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -130,7 +135,7 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
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),
|
||||
|
@ -16,7 +16,7 @@ class EditRequestURLParams extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
late List<KVRow> rows;
|
||||
late List<NameValueModel> rows;
|
||||
final random = Random.secure();
|
||||
late int seed;
|
||||
|
||||
@ -38,9 +38,11 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
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<KVRow> model = DaviModel<KVRow>(
|
||||
DaviModel<NameValueModel> model = DaviModel<NameValueModel>(
|
||||
rows: rows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
@ -50,10 +52,10 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
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<EditRequestURLParams> {
|
||||
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<EditRequestURLParams> {
|
||||
? 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<EditRequestURLParams> {
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: kTableThemeData,
|
||||
child: Davi<KVRow>(model),
|
||||
child: Davi<NameValueModel>(model),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -131,7 +136,7 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
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),
|
||||
|
@ -28,8 +28,8 @@ class _RequestEditorPaneState extends ConsumerState<RequestEditorPane> {
|
||||
} else {
|
||||
return Padding(
|
||||
padding: kIsMacOS ? kPt24o8 : kP8,
|
||||
child: Column(
|
||||
children: const [
|
||||
child: const Column(
|
||||
children: [
|
||||
EditorPaneRequestURLCard(),
|
||||
kVSpacer10,
|
||||
Expanded(
|
||||
|
@ -28,13 +28,13 @@ class _EditorPaneRequestURLCardState extends State<EditorPaneRequestURLCard> {
|
||||
),
|
||||
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(
|
||||
|
@ -13,8 +13,8 @@ class HomePage extends StatefulWidget {
|
||||
class HomePageState extends State<HomePage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: const [
|
||||
return const Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DashboardSplitView(
|
||||
sidebarWidget: CollectionPane(),
|
||||
|
@ -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<SettingsPage> {
|
||||
.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,
|
||||
|
@ -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<String, String> 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);
|
||||
}
|
||||
}
|
||||
|
@ -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<String, String>? rowsToMap(List<KVRow>? kvRows, {bool isHeader = false}) {
|
||||
Map<String, String>? rowsToMap(List<NameValueModel>? kvRows,
|
||||
{bool isHeader = false}) {
|
||||
if (kvRows == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, String> 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<KVRow>? mapToRows(Map<String, String>? kvMap) {
|
||||
List<NameValueModel>? mapToRows(Map<String, String>? kvMap) {
|
||||
if (kvMap == null) {
|
||||
return null;
|
||||
}
|
||||
List<KVRow> finalRows = [];
|
||||
List<NameValueModel> 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<String, dynamic>? 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;
|
||||
}
|
||||
}
|
||||
|
@ -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<KVRow>? requestParams,
|
||||
{String defaultUriScheme = kDefaultUriScheme}
|
||||
) {
|
||||
String? url, List<NameValueModel>? 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<String, String>? queryParams = rowsToMap(requestParams);
|
||||
if(queryParams != null){
|
||||
if(uri.hasQuery){
|
||||
if (queryParams != null) {
|
||||
if (uri.hasQuery) {
|
||||
Map<String, String> urlQueryParams = uri.queryParameters;
|
||||
queryParams = mergeMaps(urlQueryParams, queryParams);
|
||||
}
|
||||
@ -93,48 +90,58 @@ MediaType? getMediaTypeFromHeaders(Map? headers) {
|
||||
return (uri, null);
|
||||
}
|
||||
|
||||
(List<ResponseBodyView>, String?) getResponseBodyViewOptions(MediaType? mediaType){
|
||||
if(mediaType != null){
|
||||
(List<ResponseBodyView>, 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;
|
||||
}
|
||||
}
|
||||
|
@ -2,3 +2,4 @@ export 'ui_utils.dart';
|
||||
export 'convert_utils.dart';
|
||||
export 'http_utils.dart';
|
||||
export 'file_utils.dart';
|
||||
export 'window_utils.dart';
|
||||
|
18
lib/utils/window_utils.dart
Normal file
18
lib/utils/window_utils.dart
Normal file
@ -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;
|
||||
}
|
@ -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<SaveInDownloadsButton> {
|
||||
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 {
|
||||
|
@ -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<CodePreviewer> {
|
||||
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<CodePreviewer> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<TextSpan>> asyncGenerateSpans(
|
||||
String code, String? language, Map<String, TextStyle> theme, bool limitedLines) async {
|
||||
Future<List<TextSpan>> asyncGenerateSpans(String code, String? language,
|
||||
Map<String, TextStyle> 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;
|
||||
}
|
||||
|
@ -135,48 +135,55 @@ class _ViewCodePaneState extends State<ViewCodePane> {
|
||||
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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -339,8 +339,8 @@ class _ResponseBodyState extends State<ResponseBody> {
|
||||
}
|
||||
|
||||
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<BodySuccess> {
|
||||
|
||||
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(
|
||||
|
@ -76,8 +76,8 @@ class EqualSplitView extends StatefulWidget {
|
||||
class _EqualSplitViewState extends State<EqualSplitView> {
|
||||
final MultiSplitViewController _controller = MultiSplitViewController(
|
||||
areas: [
|
||||
Area(minimalSize: 300),
|
||||
Area(minimalSize: 300),
|
||||
Area(minimalSize: kMinRequestEditorDetailsCardPaneSize),
|
||||
Area(minimalSize: kMinRequestEditorDetailsCardPaneSize),
|
||||
],
|
||||
);
|
||||
|
||||
|
450
pubspec.lock
450
pubspec.lock
File diff suppressed because it is too large
Load Diff
45
pubspec.yaml
45
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
|
||||
|
505
test/codegen/dart_http_codegen_test.dart
Normal file
505
test/codegen/dart_http_codegen_test.dart
Normal file
@ -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<String,String>.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);
|
||||
});
|
||||
});
|
||||
}
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -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', () {
|
||||
|
@ -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: '''{
|
||||
|
182
test/request_models.dart
Normal file
182
test/request_models.dart
Normal file
@ -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,
|
||||
);
|
@ -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<String> result = [];
|
||||
for (var i = 0; i < lines; i++) {
|
||||
result.add(getRandomString(length));
|
||||
static String getRandomStringLines(int lines, int length) {
|
||||
List<String> result = [];
|
||||
for (var i = 0; i < lines; i++) {
|
||||
result.add(getRandomString(length));
|
||||
}
|
||||
return result.join('\n');
|
||||
}
|
||||
return result.join('\n');
|
||||
}
|
||||
|
@ -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<KVRow> kvRow3 = const [
|
||||
KVRow("TEXT", "ABC"),
|
||||
KVRow("version", 0.1),
|
||||
KVRow("month", 4)
|
||||
const kvRow3 = <NameValueModel>[
|
||||
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<String, String> value1 = {"text": "abc", "lang": "eng", "code": "1"};
|
||||
List<KVRow> result1Expected = const [
|
||||
KVRow("text", "abc"),
|
||||
KVRow("lang", "eng"),
|
||||
KVRow("code", "1")
|
||||
const result1Expected = <NameValueModel>[
|
||||
NameValueModel(name: "text", value: "abc"),
|
||||
NameValueModel(name: "lang", value: "eng"),
|
||||
NameValueModel(name: "code", value: "1")
|
||||
];
|
||||
expect(mapToRows(value1), result1Expected);
|
||||
});
|
||||
|
17
test/utils/file_utils_test.dart
Normal file
17
test/utils/file_utils_test.dart
Normal file
@ -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);
|
||||
});*/
|
||||
},
|
||||
);
|
||||
}
|
@ -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() {
|
||||
<calories>650</calories>
|
||||
</food>
|
||||
</breakfast_menu>''';
|
||||
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 = '''<html>
|
||||
String body4 = '''<html>
|
||||
<body>
|
||||
<h1>My First Heading</h1>
|
||||
<p>My first paragraph.</p>
|
||||
</body>
|
||||
</html>''';
|
||||
expect(formatBody(body4, mediaTypeHtml),body4);
|
||||
</html>''';
|
||||
expect(formatBody(body4, mediaTypeHtml), body4);
|
||||
});
|
||||
|
||||
test('Testing formatBody for html subtype values with random values', () {
|
||||
String body5 =
|
||||
'''<html>${RandomStringGenerator.getRandomStringLines(100, 10000)}</html>''';
|
||||
expect(formatBody(body5, mediaTypeHtml), null);
|
||||
});
|
||||
test(
|
||||
'Testing formatBody for html subtype values with random values within limit',
|
||||
() {
|
||||
String body6 =
|
||||
'''<html>${RandomStringGenerator.getRandomStringLines(100, 190)}</html>''';
|
||||
expect(formatBody(body6, mediaTypeHtml), body6);
|
||||
});
|
||||
});
|
||||
|
||||
test('Testing formatBody for html subtype values with random values', () {
|
||||
String body5 = '''<html>${getRandomStringLines(100, 10000)}</html>''';
|
||||
expect(formatBody(body5, mediaTypeHtml),null);
|
||||
});
|
||||
test('Testing formatBody for html subtype values with random values within limit', () {
|
||||
String body6 = '''<html>${getRandomStringLines(100, 190)}</html>''';
|
||||
expect(formatBody(body6, mediaTypeHtml),body6);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
62
test/utils/window_utils_test.dart
Normal file
62
test/utils/window_utils_test.dart
Normal file
@ -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);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
@ -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() {}
|
||||
|
@ -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',
|
||||
|
@ -69,7 +69,18 @@ void main() async {
|
||||
);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Code'), findsOneWidget);
|
||||
expect(find.byType(DropdownButton<CodegenLanguage>), findsOneWidget);
|
||||
expect(
|
||||
(tester.widget(find.byType(DropdownButton<CodegenLanguage>))
|
||||
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);
|
||||
|
@ -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: '''{
|
||||
|
@ -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")]),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -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",
|
||||
|
Reference in New Issue
Block a user