mirror of
https://github.com/foss42/apidash.git
synced 2025-05-23 09:17:04 +08:00
Merge branch 'main' into feat_ruby_net_http
This commit is contained in:
18
README.md
18
README.md
@ -127,6 +127,7 @@ API Dash currently supports API integration code generation for the following la
|
||||
| ---------------------- | ------------- | ------- |
|
||||
| cURL | | |
|
||||
| HAR | | |
|
||||
| C# | `RestSharp` | |
|
||||
| Dart | `http` | |
|
||||
| Dart | `dio` | |
|
||||
| Go | `net/http` | |
|
||||
@ -141,9 +142,10 @@ API Dash currently supports API integration code generation for the following la
|
||||
| Rust | `ureq` | |
|
||||
| Rust | `Actix Client` | |
|
||||
| Java | `asynchttpclient` | https://github.com/foss42/apidash/issues/136 |
|
||||
| Java | `HttpClient` | https://github.com/foss42/apidash/issues/137 |
|
||||
| Java | `HttpClient` | |
|
||||
| Java | `okhttp3` | |
|
||||
| Julia | `HTTP` | https://github.com/foss42/apidash/issues/154 |
|
||||
| Julia | `HTTP` | |
|
||||
| PHP | `curl` | https://github.com/foss42/apidash/issues/375 |
|
||||
| PHP | `guzzle` | https://github.com/foss42/apidash/issues/143 |
|
||||
|
||||
We welcome contributions to support other programming languages/libraries/frameworks. Please check out more details [here](https://github.com/foss42/apidash/discussions/80).
|
||||
@ -157,7 +159,16 @@ Here is the complete list of mimetypes that can be directly previewed in API Das
|
||||
| File Type | Mimetype | Extension | Comment |
|
||||
| --------- | -------------------------- | ----------------- | -------- |
|
||||
| PDF | `application/pdf` | `.pdf` | |
|
||||
| CSV | `text/csv` | `.csv` | Can be improved |
|
||||
| Video | `video/mp4` | `.mp4` | |
|
||||
| Video | `video/webm` | `.webm` | |
|
||||
| Video | `video/x-ms-wmv` | `.wmv` | |
|
||||
| Video | `video/x-ms-asf` | `.wmv` | |
|
||||
| Video | `video/avi` | `.avi` | |
|
||||
| Video | `video/msvideo` | `.avi` | |
|
||||
| Video | `video/x-msvideo` | `.avi` | |
|
||||
| Video | `video/quicktime` | `.mov` | |
|
||||
| Video | `video/x-quicktime` | `.mov` | |
|
||||
| Video | `video/x-matroska` | `.mkv` | |
|
||||
| Image | `image/apng` | `.apng` | Animated |
|
||||
| Image | `image/avif` | `.avif` | |
|
||||
| Image | `image/bmp` | `.bmp` | |
|
||||
@ -188,6 +199,7 @@ Here is the complete list of mimetypes that can be directly previewed in API Das
|
||||
| Audio | `audio/x-m4a` | `.m4a` | |
|
||||
| Audio | `audio/wav` | `.wav` | |
|
||||
| Audio | `audio/wave` | `.wav` | |
|
||||
| CSV | `text/csv` | `.csv` | Can be improved |
|
||||
|
||||
We welcome PRs to add support for previewing other multimedia mimetypes. Please go ahead and raise an issue so that we can discuss the approach.
|
||||
We are adding support for other mimetypes with each release. But, if you are looking for any particular mimetype support, please go ahead and open an issue. We will prioritize it's addition.
|
||||
|
@ -57,7 +57,7 @@ class _AppState extends ConsumerState<App> with WindowListener {
|
||||
bool isPreventClose = await windowManager.isPreventClose();
|
||||
if (isPreventClose) {
|
||||
if (ref.watch(
|
||||
settingsProvider.select((value) => value.promptBeforeClosing))) {
|
||||
settingsProvider.select((value) => value.promptBeforeClosing)) && ref.watch(hasUnsavedChangesProvider)) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => AlertDialog(
|
||||
|
@ -1,13 +1,17 @@
|
||||
import 'package:apidash/models/models.dart' show RequestModel;
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:apidash/utils/utils.dart' show getNewUuid;
|
||||
import 'csharp/rest_sharp.dart';
|
||||
import 'dart/http.dart';
|
||||
import 'dart/dio.dart';
|
||||
import 'go/http.dart';
|
||||
import 'kotlin/okhttp.dart';
|
||||
import 'php/guzzle.dart';
|
||||
import 'php/curl.dart';
|
||||
import 'python/http_client.dart';
|
||||
import 'python/requests.dart';
|
||||
import 'ruby/faraday.dart';
|
||||
import 'ruby/net_http.dart';
|
||||
import 'rust/actix.dart';
|
||||
import 'rust/curl_rust.dart';
|
||||
import 'rust/reqwest.dart';
|
||||
@ -20,7 +24,6 @@ import 'julia/http.dart';
|
||||
import 'java/okhttp.dart';
|
||||
import 'java/async_http_client.dart';
|
||||
import 'java/httpclient.dart';
|
||||
import 'ruby/net_http.dart';
|
||||
|
||||
class Codegen {
|
||||
String? getCode(
|
||||
@ -61,7 +64,7 @@ class Codegen {
|
||||
case CodegenLanguage.javaAsyncHttpClient:
|
||||
return JavaAsyncHttpClientGen().getCode(rM);
|
||||
case CodegenLanguage.javaHttpClient:
|
||||
return JavaHttpClientCodeGen().getCode(rM);
|
||||
return JavaHttpClientCodeGen().getCode(rM, boundary: boundary);
|
||||
case CodegenLanguage.javaOkHttp:
|
||||
return JavaOkHttpCodeGen().getCode(rM);
|
||||
case CodegenLanguage.juliaHttp:
|
||||
@ -73,6 +76,10 @@ class Codegen {
|
||||
.getCode(rM, boundary: boundary ?? getNewUuid());
|
||||
case CodegenLanguage.pythonRequests:
|
||||
return PythonRequestsCodeGen().getCode(rM, boundary: boundary);
|
||||
case CodegenLanguage.rubyFaraday:
|
||||
return RubyFaradayCodeGen().getCode(rM);
|
||||
case CodegenLanguage.rubyNetHttp:
|
||||
return rubyCodeGen().getCode(rM);
|
||||
case CodegenLanguage.rustActix:
|
||||
return RustActixCodeGen().getCode(rM, boundary: boundary);
|
||||
case CodegenLanguage.rustCurl:
|
||||
@ -83,8 +90,10 @@ class Codegen {
|
||||
return RustUreqCodeGen().getCode(rM, boundary: boundary);
|
||||
case CodegenLanguage.phpGuzzle:
|
||||
return PhpGuzzleCodeGen().getCode(rM);
|
||||
case CodegenLanguage.rubyNetHttp:
|
||||
return rubyCodeGen().getCode(rM);
|
||||
case CodegenLanguage.phpCurl:
|
||||
return PHPcURLCodeGen().getCode(rM);
|
||||
case CodegenLanguage.cSharpRestSharp:
|
||||
return CSharpRestSharp().getCode(rM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
197
lib/codegen/csharp/rest_sharp.dart
Normal file
197
lib/codegen/csharp/rest_sharp.dart
Normal file
@ -0,0 +1,197 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:jinja/jinja.dart' as jj;
|
||||
import '../../models/request_model.dart';
|
||||
import '../../extensions/extensions.dart';
|
||||
import '../../utils/http_utils.dart';
|
||||
|
||||
class CSharpRestSharp {
|
||||
String kStringImports = """
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
""";
|
||||
|
||||
String kStringInit = """
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
""";
|
||||
|
||||
String kInitClientTemplate = """
|
||||
const String _baseUrl = "{{baseUrl}}";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
|
||||
""";
|
||||
|
||||
String kMethodTypeTemplate = """
|
||||
var request = new RestRequest("{{path}}", Method.{{method}});
|
||||
|
||||
|
||||
""";
|
||||
|
||||
String kTemplateParams = """
|
||||
request.AddQueryParameter("{{param}}", "{{value}}");
|
||||
|
||||
""";
|
||||
|
||||
String kTemplateHeaders = """
|
||||
request.AddHeader("{{header}}", "{{value}}");
|
||||
|
||||
""";
|
||||
|
||||
String kTemplateFormData = """
|
||||
{% if type == "text" -%}
|
||||
request.AddParameter("{{name}}", "{{value}}", ParameterType.GetOrPost);
|
||||
{% else -%}
|
||||
request.AddFile("{{name}}", "{{value}}", options: options);
|
||||
{% endif -%}
|
||||
""";
|
||||
|
||||
String kStringFormDataOption = """
|
||||
request.AlwaysMultipartFormData = true;
|
||||
""";
|
||||
|
||||
String kStringFormdataFileOption = """
|
||||
var options = new FileParameterOptions
|
||||
{
|
||||
DisableFilenameEncoding = true
|
||||
};
|
||||
""";
|
||||
|
||||
String kTemplateJsonData = """
|
||||
var jsonBody = new {{jsonData}};
|
||||
request.AddJsonBody(jsonBody);
|
||||
|
||||
|
||||
""";
|
||||
|
||||
String kTemplateTextData = """
|
||||
var textBody = {{textData}};
|
||||
request.AddStringBody(textBody, ContentType.Plain);
|
||||
|
||||
|
||||
""";
|
||||
|
||||
String kStringEnd = """
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
String? getCode(RequestModel requestModel) {
|
||||
try {
|
||||
String result = "";
|
||||
var rec = getValidRequestUri(
|
||||
requestModel.url,
|
||||
requestModel.enabledRequestParams,
|
||||
);
|
||||
Uri? uri = rec.$1;
|
||||
if (uri != null) {
|
||||
jj.Template kNodejsImportTemplate = jj.Template(kStringImports);
|
||||
String importsData = kNodejsImportTemplate.render();
|
||||
result += importsData;
|
||||
|
||||
result += kStringInit;
|
||||
|
||||
jj.Template templateInitClient = jj.Template(kInitClientTemplate);
|
||||
String initClient = templateInitClient
|
||||
.render({"baseUrl": "${uri.scheme}://${uri.authority}"});
|
||||
result += initClient;
|
||||
|
||||
jj.Template templateMethodType = jj.Template(kMethodTypeTemplate);
|
||||
String methodType = templateMethodType.render({
|
||||
"path": uri.path,
|
||||
"method": requestModel.method.name.capitalize(),
|
||||
});
|
||||
result += methodType;
|
||||
|
||||
if (uri.hasQuery) {
|
||||
var params = uri.queryParameters;
|
||||
if (params.isNotEmpty) {
|
||||
jj.Template templateParams = jj.Template(kTemplateParams);
|
||||
String paramsResult = "";
|
||||
for (var item in params.entries) {
|
||||
paramsResult += templateParams
|
||||
.render({"param": item.key, "value": item.value});
|
||||
}
|
||||
result += "$paramsResult\n";
|
||||
}
|
||||
}
|
||||
|
||||
var headersList = requestModel.enabledRequestHeaders;
|
||||
if (headersList != null ||
|
||||
requestModel.hasJsonData ||
|
||||
requestModel.hasTextData) {
|
||||
var headers = requestModel.enabledHeadersMap;
|
||||
if (requestModel.hasJsonData || requestModel.hasTextData) {
|
||||
headers[kHeaderContentType] =
|
||||
requestModel.requestBodyContentType.header;
|
||||
}
|
||||
if (headers.isNotEmpty) {
|
||||
jj.Template templateHeaders = jj.Template(kTemplateHeaders);
|
||||
String headersResult = "";
|
||||
for (var item in headers.entries) {
|
||||
headersResult += templateHeaders
|
||||
.render({"header": item.key, "value": item.value});
|
||||
}
|
||||
result += "$headersResult\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (requestModel.hasFormData) {
|
||||
jj.Template templateFormData = jj.Template(kTemplateFormData);
|
||||
String formDataResult = "";
|
||||
for (var data in requestModel.formDataMapList) {
|
||||
formDataResult += templateFormData.render({
|
||||
"name": data["name"],
|
||||
"value": data["value"],
|
||||
"type": data["type"]
|
||||
});
|
||||
}
|
||||
result += kStringFormDataOption;
|
||||
if (requestModel.hasFileInFormData) {
|
||||
result += kStringFormdataFileOption;
|
||||
}
|
||||
result += "$formDataResult\n";
|
||||
}
|
||||
|
||||
if (requestModel.hasJsonData) {
|
||||
var templateJsonData = jj.Template(kTemplateJsonData);
|
||||
Map<String, dynamic> bodyData =
|
||||
json.decode(requestModel.requestBody!);
|
||||
List<String> jsonArr = [];
|
||||
|
||||
bodyData.forEach((key, value) {
|
||||
jsonArr += ["$key = \"$value\""];
|
||||
});
|
||||
String jsonDataResult = "{\n${jsonArr.join(",\n")}\n}";
|
||||
|
||||
result += templateJsonData.render({"jsonData": jsonDataResult});
|
||||
}
|
||||
|
||||
if (requestModel.hasTextData) {
|
||||
jj.Template templateTextData = jj.Template(kTemplateTextData);
|
||||
result += templateTextData
|
||||
.render({"textData": jsonEncode(requestModel.requestBody)});
|
||||
}
|
||||
|
||||
result += kStringEnd;
|
||||
}
|
||||
return result;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -148,9 +148,9 @@ public class Main {
|
||||
// especially sets up Content-Type header if the request has a body
|
||||
// and Content-Type is not explicitely set by the developer
|
||||
if (hasBody &&
|
||||
!requestModel.enabledHeadersMap.containsKey('Content-Type')) {
|
||||
!requestModel.enabledHeadersMap.containsKey(kHeaderContentType)) {
|
||||
result += templateRequestHeader
|
||||
.render({"name": 'Content-Type', "value": contentType});
|
||||
.render({"name": kHeaderContentType, "value": contentType});
|
||||
}
|
||||
|
||||
// setting up rest of the request headers
|
||||
|
@ -1,183 +1,197 @@
|
||||
import 'dart:convert';
|
||||
import 'package:jinja/jinja.dart' as jj;
|
||||
import 'package:apidash/utils/utils.dart'
|
||||
show getValidRequestUri, requestModelToHARJsonRequest, stripUriParams;
|
||||
import '../../models/request_model.dart';
|
||||
show getValidRequestUri, requestModelToHARJsonRequest;
|
||||
import 'package:apidash/models/models.dart' show RequestModel;
|
||||
import 'package:apidash/consts.dart';
|
||||
|
||||
class JavaHttpClientCodeGen {
|
||||
final String kTemplateStart = """
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
final String kTemplateStart = """import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.net.http.HttpHeaders;
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
import java.net.http.HttpResponse.BodyHandlers;
|
||||
import java.io.IOException;
|
||||
{% if hasFormData %}import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;{% endif %}
|
||||
|
||||
public class JavaHttpClientExample {
|
||||
|
||||
public static void main(String[] args) throws IOException, InterruptedException {
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
""";
|
||||
final String kTemplateUrl = '''
|
||||
|
||||
String url = "{{url}}";
|
||||
|
||||
''';
|
||||
|
||||
final String kTemplateUrlQuery = '''
|
||||
|
||||
String url = "{{url}}";
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
URI uri = new URI(url);
|
||||
url = uri.resolve("{{params}}").toString();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
|
||||
''';
|
||||
|
||||
String kTemplateRequestBody = '''
|
||||
|
||||
String body = "{{body}}";
|
||||
|
||||
''';
|
||||
|
||||
final String kStringRequestStart = """
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(url))
|
||||
""";
|
||||
|
||||
final String kTemplateRequestEnd = """
|
||||
.{{method}}({{body}})
|
||||
.build();
|
||||
String kTemplateUrl = """
|
||||
URI uri = URI.create("{{url}}");
|
||||
|
||||
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
|
||||
System.out.println(response.statusCode());
|
||||
System.out.println(response.body());
|
||||
""";
|
||||
|
||||
String kTemplateFormHeaderContentType = '''
|
||||
multipart/form-data; boundary={{boundary}}''';
|
||||
|
||||
String kTemplateMethod = """
|
||||
{% if method == 'get' %}
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET();
|
||||
{% elif method == 'post' %}
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).POST({% if hasBody %}bodyPublisher{% else %}HttpRequest.BodyPublishers.noBody(){% endif %});
|
||||
{% elif method == 'put' %}
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).PUT({% if hasBody %}bodyPublisher{% else %}HttpRequest.BodyPublishers.noBody(){% endif %});
|
||||
{% elif method == 'delete' %}
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("DELETE", {% if hasBody %}bodyPublisher{% else %}HttpRequest.BodyPublishers.noBody(){% endif %});
|
||||
{% elif method == 'patch' %}
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("PATCH", {% if hasBody %}bodyPublisher{% else %}HttpRequest.BodyPublishers.noBody(){% endif %});
|
||||
{% elif method == 'head' %}
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).method("HEAD", HttpRequest.BodyPublishers.noBody());
|
||||
{% endif %}
|
||||
""";
|
||||
|
||||
String kTemplateRawBody = """
|
||||
HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(\"\"\"
|
||||
{{body}}\"\"\");
|
||||
""";
|
||||
|
||||
String kTemplateJsonBody = """
|
||||
HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.ofString(\"\"\"
|
||||
{{body}}\"\"\");
|
||||
""";
|
||||
|
||||
String kTemplateFormData = """
|
||||
String boundary = "{{boundary}}";
|
||||
Map<Object, Object> data = new HashMap<>();
|
||||
{% for field in fields %}
|
||||
{% if field.type == "file" %}data.put("{{field.name}}", Paths.get("{{field.value}}"));{% else %}data.put("{{field.name}}", "{{field.value}}");{% endif %}{% endfor %}
|
||||
HttpRequest.BodyPublisher bodyPublisher = buildMultipartFormData(data, boundary);
|
||||
""";
|
||||
|
||||
String kTemplateHeader = """
|
||||
requestBuilder = requestBuilder.headers({% for header, value in headers %}
|
||||
"{{header}}", "{{value}}"{% if not loop.last %},{% endif %}{% endfor %}
|
||||
);
|
||||
|
||||
""";
|
||||
|
||||
final String kTemplateEnd = """
|
||||
HttpResponse<String> response = client.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString());
|
||||
System.out.println("Response body: " + response.body());
|
||||
System.out.println("Response code: " + response.statusCode());
|
||||
} catch (IOException | InterruptedException e) {
|
||||
System.out.println("An error occurred: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
\n
|
||||
{% if hasFormData %}
|
||||
private static HttpRequest.BodyPublisher buildMultipartFormData(Map<Object, Object> data, String boundary) throws IOException {
|
||||
var byteArrays = new ArrayList<byte[]>();
|
||||
var CRLF = "\\r\\n".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
for (Map.Entry<Object, Object> entry : data.entrySet()) {
|
||||
byteArrays.add(("--" + boundary + "\\r\\n").getBytes(StandardCharsets.UTF_8));
|
||||
if (entry.getValue() instanceof Path) {
|
||||
var file = (Path) entry.getValue();
|
||||
var fileName = file.getFileName().toString();
|
||||
byteArrays.add(("Content-Disposition: form-data; name=\\"" + entry.getKey() + "\\"; filename=\\"" + fileName + "\\"\\r\\n").getBytes(StandardCharsets.UTF_8));
|
||||
byteArrays.add(("Content-Type: " + Files.probeContentType(file) + "\\r\\n\\r\\n").getBytes(StandardCharsets.UTF_8));
|
||||
byteArrays.add(Files.readAllBytes(file));
|
||||
byteArrays.add(CRLF);
|
||||
} else {
|
||||
byteArrays.add(("Content-Disposition: form-data; name=\\"" + entry.getKey() + "\\"\\r\\n\\r\\n").getBytes(StandardCharsets.UTF_8));
|
||||
byteArrays.add(entry.getValue().toString().getBytes(StandardCharsets.UTF_8));
|
||||
byteArrays.add(CRLF);
|
||||
}
|
||||
}
|
||||
byteArrays.add(("--" + boundary + "--\\r\\n").getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
return HttpRequest.BodyPublishers.ofByteArrays(byteArrays);
|
||||
}{% endif %}
|
||||
}
|
||||
""";
|
||||
|
||||
String? getCode(
|
||||
RequestModel requestModel,
|
||||
) {
|
||||
RequestModel requestModel, {
|
||||
String? boundary,
|
||||
}) {
|
||||
try {
|
||||
String result = "";
|
||||
bool hasQuery = false;
|
||||
bool hasBody = false;
|
||||
bool hasJsonBody = false;
|
||||
var requestBody = requestModel.requestBody;
|
||||
String url = requestModel.url;
|
||||
|
||||
result += jj.Template(kTemplateStart).render({
|
||||
"hasFormData": requestModel.hasFormData,
|
||||
});
|
||||
|
||||
var rec = getValidRequestUri(
|
||||
requestModel.url,
|
||||
url,
|
||||
requestModel.enabledRequestParams,
|
||||
);
|
||||
|
||||
Uri? uri = rec.$1;
|
||||
|
||||
var harJson =
|
||||
requestModelToHARJsonRequest(requestModel, useEnabled: true);
|
||||
|
||||
if (uri != null) {
|
||||
String url = stripUriParams(uri);
|
||||
|
||||
if (uri.hasQuery) {
|
||||
var params = uri.queryParameters;
|
||||
if (params.isNotEmpty) {
|
||||
hasQuery = true;
|
||||
var templateParams = jj.Template(kTemplateUrlQuery);
|
||||
result += templateParams.render({"url": url, "params": uri.query});
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasQuery) {
|
||||
var templateUrl = jj.Template(kTemplateUrl);
|
||||
result += templateUrl.render({"url": url});
|
||||
}
|
||||
var rM = requestModel.copyWith(url: url);
|
||||
result += templateUrl.render({"url": harJson["url"]});
|
||||
|
||||
var harJson = requestModelToHARJsonRequest(rM, useEnabled: true);
|
||||
|
||||
var method = requestModel.method;
|
||||
var requestBody = requestModel.requestBody;
|
||||
if (requestModel.hasFormData &&
|
||||
requestModel.formDataMapList.isNotEmpty &&
|
||||
kMethodsWithBody.contains(method)) {
|
||||
var formDataList = requestModel.formDataMapList;
|
||||
result += """
|
||||
StringBuilder formData = new StringBuilder();
|
||||
formData.append(""";
|
||||
|
||||
for (var formDataMap in formDataList) {
|
||||
result += '"""${formDataMap['name']}=${formDataMap['value']}&""",';
|
||||
}
|
||||
|
||||
result = result.substring(0, result.length - 1);
|
||||
result += ");\n";
|
||||
hasBody = true;
|
||||
} else if (kMethodsWithBody.contains(method) && requestBody != null) {
|
||||
var contentLength = utf8.encode(requestBody).length;
|
||||
if (contentLength > 0) {
|
||||
var templateBody = jj.Template(kTemplateRequestBody);
|
||||
hasBody = true;
|
||||
hasJsonBody =
|
||||
requestBody.startsWith("{") && requestBody.endsWith("}");
|
||||
if (harJson["postData"]?["text"] != null) {
|
||||
result += templateBody.render({
|
||||
"body": kEncoder.convert(harJson["postData"]["text"]).substring(
|
||||
1, kEncoder.convert(harJson["postData"]["text"]).length - 1)
|
||||
String? bodyPublisher = "";
|
||||
if (requestModel.hasTextData) {
|
||||
var templateBody = jj.Template(kTemplateRawBody);
|
||||
bodyPublisher = templateBody.render({"body": requestBody});
|
||||
} else if (requestModel.hasJsonData) {
|
||||
var templateBody = jj.Template(kTemplateJsonBody);
|
||||
bodyPublisher = templateBody.render({"body": requestBody});
|
||||
} else if (requestModel.hasFormData) {
|
||||
var templateFormData = jj.Template(kTemplateFormData);
|
||||
bodyPublisher = templateFormData.render({
|
||||
"fields": requestModel.formDataMapList,
|
||||
"boundary": boundary,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = kTemplateStart + result;
|
||||
result += kStringRequestStart;
|
||||
result += bodyPublisher;
|
||||
|
||||
var methodTemplate = jj.Template(kTemplateMethod);
|
||||
result += methodTemplate.render({
|
||||
"method": requestModel.method.name,
|
||||
"hasBody": requestModel.hasBody,
|
||||
});
|
||||
|
||||
var headersList = requestModel.enabledRequestHeaders;
|
||||
var contentType = requestModel.requestBodyContentType.header;
|
||||
if (hasBody &&
|
||||
!requestModel.enabledHeadersMap.containsKey('Content-Type')) {
|
||||
result =
|
||||
"""$result .header("Content-Type", "$contentType")\n""";
|
||||
}
|
||||
if (headersList != null) {
|
||||
if (headersList != null || requestModel.hasBody) {
|
||||
var headers = requestModel.enabledHeadersMap;
|
||||
if (requestModel.hasJsonData || requestModel.hasTextData) {
|
||||
headers.putIfAbsent(kHeaderContentType,
|
||||
() => requestModel.requestBodyContentType.header);
|
||||
}
|
||||
if (requestModel.hasFormData) {
|
||||
var formDataHeader = jj.Template(kTemplateFormHeaderContentType);
|
||||
headers.putIfAbsent(
|
||||
kHeaderContentType,
|
||||
() => formDataHeader.render({
|
||||
"boundary": boundary,
|
||||
}));
|
||||
}
|
||||
if (headers.isNotEmpty) {
|
||||
result += getHeaders(headers, hasJsonBody);
|
||||
}
|
||||
}
|
||||
|
||||
var templateRequestEnd = jj.Template(kTemplateRequestEnd);
|
||||
|
||||
if (kMethodsWithBody.contains(method)) {
|
||||
result += templateRequestEnd.render({
|
||||
"method": method.name.toUpperCase(),
|
||||
"body": hasBody
|
||||
? "BodyPublishers.ofString(body)"
|
||||
: "BodyPublishers.noBody()"
|
||||
var templateHeader = jj.Template(kTemplateHeader);
|
||||
result += templateHeader.render({
|
||||
"headers": headers,
|
||||
});
|
||||
} else {
|
||||
result += templateRequestEnd
|
||||
.render({"method": method.name.toUpperCase(), "body": ""});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
var templateEnd = jj.Template(kTemplateEnd);
|
||||
result += templateEnd.render({
|
||||
"hasFormData": requestModel.hasFormData,
|
||||
"boundary": boundary,
|
||||
});
|
||||
}
|
||||
|
||||
return result.replaceAll(RegExp('\\n\\n+'), '\n\n');
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String getHeaders(Map<String, String> headers, hasJsonBody) {
|
||||
String result = "";
|
||||
for (final k in headers.keys) {
|
||||
if (k.toLowerCase() == 'authorization') {
|
||||
result = """$result .header("$k", "${headers[k]}")\n""";
|
||||
} else {
|
||||
result = """$result .header("$k", "${headers[k]}")\n""";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ axios(config)
|
||||
m[i["name"]] = i["value"];
|
||||
}
|
||||
if (requestModel.hasFormData) {
|
||||
m[kHeaderContentType] = 'multipart/form-data';
|
||||
m[kHeaderContentType] = ContentType.formdata.header;
|
||||
}
|
||||
result += templateHeader
|
||||
.render({"headers": padMultilineString(kEncoder.convert(m), 2)});
|
||||
|
@ -99,7 +99,7 @@ fetch(url, options)
|
||||
var m = {};
|
||||
for (var i in headers) {
|
||||
// fetch can automatically add the Content-Type header when FormData is passed as body
|
||||
if (i["name"] == "Content-Type" && requestModel.hasFormData) {
|
||||
if (i["name"] == kHeaderContentType && requestModel.hasFormData) {
|
||||
continue;
|
||||
}
|
||||
m[i["name"]] = i["value"];
|
||||
|
@ -1,98 +1,73 @@
|
||||
import 'dart:io';
|
||||
import 'dart:convert';
|
||||
import 'package:jinja/jinja.dart' as jj;
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:apidash/utils/utils.dart'
|
||||
show getNewUuid, getValidRequestUri, padMultilineString, stripUriParams;
|
||||
show getValidRequestUri, stripUriParams;
|
||||
import 'package:apidash/models/models.dart' show RequestModel;
|
||||
|
||||
class JuliaHttpClientCodeGen {
|
||||
final String kTemplateStart = """using HTTP,JSON
|
||||
final String kTemplateStart = """
|
||||
using HTTP{% if hasJson %}, JSON{% endif %}
|
||||
\n
|
||||
""";
|
||||
|
||||
final String kTemplateUrl = """
|
||||
url = "{{url}}"
|
||||
|
||||
\n
|
||||
""";
|
||||
|
||||
String kTemplateParams = """
|
||||
{% set new_params = params | replace(":", "=>") | replace("{", "(") | replace("}", ")") %}
|
||||
|
||||
params = Dict{{new_params}}
|
||||
""";
|
||||
|
||||
int kParamsPadding = 9;
|
||||
|
||||
String kTemplateBody = '''
|
||||
{% set new_params = body | replace(":", "=>") | replace("{", "(") | replace("}", ")") %}
|
||||
|
||||
payload = Dict{{new_params}}
|
||||
''';
|
||||
|
||||
String kTemplateJson = """
|
||||
{% set new_params = body | replace(":", "=>") | replace("{", "(") | replace("}", ")") %}
|
||||
|
||||
payload = Dict{{new_params}}
|
||||
params = Dict(
|
||||
{%- for name, value in params %}
|
||||
"{{ name }}" => "{{ value }}",
|
||||
{%- endfor %}
|
||||
)
|
||||
\n
|
||||
""";
|
||||
|
||||
String kTemplateHeaders = """
|
||||
{% set new_params = headers | replace(":", "=>") | replace("{", "(") | replace("}", ")") %}
|
||||
|
||||
headers = Dict{{new_params}}
|
||||
headers = Dict(
|
||||
{%- for name, value in headers %}
|
||||
"{{ name }}" => "{{ value }}",
|
||||
{%- endfor %}
|
||||
)
|
||||
\n
|
||||
""";
|
||||
|
||||
String kTemplateFormHeaderContentType = '''
|
||||
multipart/form-data; boundary={{boundary}}''';
|
||||
final String kTemplateFormDataBody = '''
|
||||
data = Dict(
|
||||
{%- for data in formdata %}
|
||||
{%- if data.type == "text" %}
|
||||
"{{ data.name }}" => "{{ data.value }}",
|
||||
{%- else %}
|
||||
"{{ data.name }}" => open("{{ data.value }}"),
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
)
|
||||
|
||||
int kHeadersPadding = 10;
|
||||
payload = HTTP.Form(data)
|
||||
\n
|
||||
''';
|
||||
|
||||
String kTemplateBody = '''
|
||||
payload = """{{ body }}"""
|
||||
\n
|
||||
''';
|
||||
|
||||
String kTemplateRequest = """
|
||||
|
||||
|
||||
response = HTTP.{{method}}(url
|
||||
response = HTTP.request("{{ method | upper }}", url
|
||||
""";
|
||||
|
||||
final String kStringFormDataBody = r'''
|
||||
function build_data_list(fields)
|
||||
dataList = []
|
||||
for field in fields
|
||||
name = field["name"]
|
||||
value = field["value"]
|
||||
type_ = get(field, "type", "text")
|
||||
|
||||
push!(dataList, b"--{{boundary}}")
|
||||
if type_ == "text"
|
||||
push!(dataList, b"Content-Disposition: form-data; name=\"$name\"")
|
||||
push!(dataList, b"Content-Type: text/plain")
|
||||
push!(dataList, b"")
|
||||
push!(dataList, codeunits(value))
|
||||
elseif type_ == "file"
|
||||
push!(dataList, b"Content-Disposition: form-data; name=\"$name\"; filename=\"$value\"")
|
||||
push!(dataList, b"Content-Type: $value")
|
||||
push!(dataList, b"")
|
||||
push!(dataList, String(read(value)))
|
||||
end
|
||||
end
|
||||
push!(dataList, "--{{boundary}}--")
|
||||
push!(dataList, b"")
|
||||
return dataList
|
||||
end
|
||||
|
||||
dataList = build_data_list({{fields_list}})
|
||||
payload = join(dataList, b"\r\n")
|
||||
''';
|
||||
|
||||
String kStringRequestParams = """, query=params""";
|
||||
|
||||
String kStringRequestBody = """, payload=payload""";
|
||||
|
||||
String kStringRequestJson = """, JSON.json(payload)""";
|
||||
String kStringRequestBody = """, body=payload""";
|
||||
|
||||
String kStringRequestHeaders = """, headers=headers""";
|
||||
|
||||
final String kStringRequestEnd = """
|
||||
)
|
||||
final String kStringRequestEnd = r"""
|
||||
, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
|
||||
String? getCode(RequestModel requestModel) {
|
||||
@ -100,9 +75,7 @@ println("Response Body:", String(response.body))
|
||||
String result = "";
|
||||
bool hasQuery = false;
|
||||
bool hasHeaders = false;
|
||||
bool hasBody = false;
|
||||
bool hasJsonBody = false;
|
||||
String uuid = getNewUuid();
|
||||
bool addHeaderForBody = false;
|
||||
|
||||
var rec = getValidRequestUri(
|
||||
requestModel.url,
|
||||
@ -110,86 +83,80 @@ println("Response Body:", String(response.body))
|
||||
);
|
||||
Uri? uri = rec.$1;
|
||||
if (uri != null) {
|
||||
var templateStartUrl = jj.Template(kTemplateStart);
|
||||
result += templateStartUrl.render({
|
||||
"url": stripUriParams(uri),
|
||||
final templateStart = jj.Template(kTemplateStart);
|
||||
result += templateStart.render({
|
||||
// "hasJson": requestModel.hasBody && requestModel.hasJsonContentType && requestModel.hasJsonData,
|
||||
"hasJson":
|
||||
false, // we manually send false because we do not require JSON package
|
||||
});
|
||||
|
||||
final templateUrl = jj.Template(kTemplateUrl);
|
||||
result += templateUrl.render({"url": stripUriParams(uri)});
|
||||
|
||||
if (uri.hasQuery) {
|
||||
var params = uri.queryParameters;
|
||||
if (params.isNotEmpty) {
|
||||
hasQuery = true;
|
||||
var templateParams = jj.Template(kTemplateParams);
|
||||
var paramsString = kEncoder.convert(params);
|
||||
paramsString = padMultilineString(paramsString, kParamsPadding);
|
||||
result += templateParams.render({"params": paramsString});
|
||||
final templateParams = jj.Template(kTemplateParams);
|
||||
result += templateParams.render({"params": params});
|
||||
}
|
||||
}
|
||||
|
||||
if (requestModel.hasJsonData) {
|
||||
hasJsonBody = true;
|
||||
var templateBody = jj.Template(kTemplateJson);
|
||||
result += templateBody.render({"body": requestModel.requestBody});
|
||||
} else if (requestModel.hasTextData) {
|
||||
hasBody = true;
|
||||
var templateBody = jj.Template(kTemplateBody);
|
||||
result += templateBody.render({"body": requestModel.requestBody});
|
||||
if (requestModel.hasJsonData || requestModel.hasTextData) {
|
||||
addHeaderForBody = true;
|
||||
final templateBody = jj.Template(kTemplateBody);
|
||||
var bodyStr = requestModel.requestBody;
|
||||
result += templateBody.render({"body": bodyStr});
|
||||
}
|
||||
|
||||
var headersList = requestModel.enabledRequestHeaders;
|
||||
if (headersList != null || hasBody) {
|
||||
var headers = requestModel.enabledHeadersMap;
|
||||
if (requestModel.hasFormData) {
|
||||
var formHeaderTemplate =
|
||||
jj.Template(kTemplateFormHeaderContentType);
|
||||
headers[HttpHeaders.contentTypeHeader] = formHeaderTemplate.render({
|
||||
"boundary": uuid,
|
||||
});
|
||||
}
|
||||
if (headers.isNotEmpty || hasBody) {
|
||||
hasHeaders = true;
|
||||
if (hasBody) {
|
||||
headers[HttpHeaders.contentTypeHeader] =
|
||||
requestModel.requestBodyContentType.header;
|
||||
}
|
||||
var headersString = kEncoder.convert(headers);
|
||||
headersString = padMultilineString(headersString, kHeadersPadding);
|
||||
var templateHeaders = jj.Template(kTemplateHeaders);
|
||||
result += templateHeaders.render({"headers": headersString});
|
||||
}
|
||||
}
|
||||
if (requestModel.hasFormData) {
|
||||
var formDataBodyData = jj.Template(kStringFormDataBody);
|
||||
final formDataBodyData = jj.Template(kTemplateFormDataBody);
|
||||
result += formDataBodyData.render(
|
||||
{
|
||||
"fields_list": json.encode(requestModel.formDataMapList),
|
||||
"boundary": uuid,
|
||||
"hasFile": requestModel.hasFileInFormData,
|
||||
"formdata": requestModel.formDataMapList,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
var headersList = requestModel.enabledRequestHeaders;
|
||||
if (headersList != null || addHeaderForBody) {
|
||||
var headers = requestModel.enabledHeadersMap;
|
||||
|
||||
if (!requestModel.hasContentTypeHeader) {
|
||||
if (addHeaderForBody) {
|
||||
headers[HttpHeaders.contentTypeHeader] =
|
||||
requestModel.requestBodyContentType.header;
|
||||
}
|
||||
}
|
||||
|
||||
if (headers.isNotEmpty) {
|
||||
hasHeaders = true;
|
||||
var templateHeaders = jj.Template(kTemplateHeaders);
|
||||
result += templateHeaders.render({"headers": headers});
|
||||
}
|
||||
}
|
||||
|
||||
var templateRequest = jj.Template(kTemplateRequest);
|
||||
result += templateRequest.render({
|
||||
"method": requestModel.method.name.toLowerCase(),
|
||||
"method": requestModel.method.name,
|
||||
});
|
||||
|
||||
if (hasHeaders) {
|
||||
result += kStringRequestHeaders;
|
||||
}
|
||||
|
||||
if (requestModel.hasBody) {
|
||||
result += kStringRequestBody;
|
||||
}
|
||||
|
||||
if (hasQuery) {
|
||||
result += kStringRequestParams;
|
||||
}
|
||||
|
||||
if (hasBody || requestModel.hasFormData) {
|
||||
result += kStringRequestBody;
|
||||
}
|
||||
|
||||
if (hasJsonBody || requestModel.hasFormData) {
|
||||
result += kStringRequestJson;
|
||||
}
|
||||
|
||||
if (hasHeaders || requestModel.hasFormData) {
|
||||
result += kStringRequestHeaders;
|
||||
}
|
||||
|
||||
result += kStringRequestEnd;
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (e) {
|
||||
return null;
|
||||
|
342
lib/codegen/php/curl.dart
Normal file
342
lib/codegen/php/curl.dart
Normal file
@ -0,0 +1,342 @@
|
||||
import 'dart:convert';
|
||||
import 'package:jinja/jinja.dart' as jj;
|
||||
import 'package:apidash/utils/utils.dart'
|
||||
show getNewUuid, getValidRequestUri, requestModelToHARJsonRequest;
|
||||
import 'package:apidash/models/models.dart' show RequestModel;
|
||||
import 'package:apidash/consts.dart';
|
||||
|
||||
class PHPcURLCodeGen {
|
||||
final String kTemplateStart = """
|
||||
<?php
|
||||
|
||||
""";
|
||||
|
||||
final String kTemplateUri = """
|
||||
\$uri = "{{uri}}";
|
||||
|
||||
""";
|
||||
|
||||
//defining query parameters
|
||||
String kTemplateParams = """
|
||||
|
||||
\$queryParams = [{{params}}];
|
||||
\$queryString = "?" . http_build_query(\$queryParams);
|
||||
if (count(\$queryParams) > 0) {
|
||||
\$uri .= \$queryString;
|
||||
}
|
||||
|
||||
""";
|
||||
|
||||
//initialising the request
|
||||
String kTemplateRequestInit = """
|
||||
|
||||
\$request = curl_init(\$uri);
|
||||
|
||||
""";
|
||||
|
||||
String kTemplateBody = """
|
||||
|
||||
\$request_body = <<<EOF
|
||||
{{body}}
|
||||
EOF;
|
||||
|
||||
""";
|
||||
//specifying headers
|
||||
String kTemplateHeaders = """
|
||||
|
||||
\$headers = [{{headers}}];
|
||||
curl_setopt(\$request, CURLOPT_HTTPHEADER, \$headers);
|
||||
|
||||
""";
|
||||
|
||||
String kTemplateFormHeaderContentType = '''
|
||||
multipart/form-data; boundary={{boundary}}''';
|
||||
|
||||
String kTemplateRequest = """
|
||||
|
||||
curl_setopt(\$request, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt(\$request, {{method}}, 1);
|
||||
|
||||
""";
|
||||
|
||||
//passing the request body
|
||||
String kStringRequestBody = """
|
||||
curl_setopt(\$request, CURLOPT_POSTFIELDS, \$request_body);
|
||||
|
||||
""";
|
||||
|
||||
//ending template
|
||||
final String kStringRequestEnd = """
|
||||
\$response = curl_exec(\$request);
|
||||
curl_close(\$request);
|
||||
var_dump(\$response);
|
||||
|
||||
""";
|
||||
|
||||
//template for generating unique boundary
|
||||
String kBoundaryUniqueIdTemplate = """
|
||||
\$boundary = "{{uuid}}";
|
||||
|
||||
""";
|
||||
|
||||
//
|
||||
String kFileClassString = """
|
||||
class File
|
||||
{
|
||||
public string \$name;
|
||||
public string \$filename;
|
||||
public string \$content;
|
||||
|
||||
function __construct(\$name, \$filename)
|
||||
{
|
||||
\$this->name = \$name;
|
||||
\$this->filename = \$filename;
|
||||
\$available_content = file_get_contents(\$this->filename);
|
||||
\$this->content = \$available_content ? \$available_content : "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
""";
|
||||
|
||||
//function to build formdata without 'file' type
|
||||
String kBuildFormDataFunctionWithoutFilesString = """
|
||||
function build_data(\$boundary, \$fields)
|
||||
{
|
||||
\$data = '';
|
||||
\$eol = "\\r\\n";
|
||||
|
||||
\$delimiter = '-------------' . \$boundary;
|
||||
|
||||
foreach (\$fields as \$name => \$content) {
|
||||
\$data .= "--" . \$delimiter . \$eol
|
||||
. 'Content-Disposition: form-data; name="' . \$name . "\\"" . \$eol . \$eol
|
||||
. \$content . \$eol;
|
||||
}
|
||||
\$data .= "--" . \$delimiter . "--" . \$eol;
|
||||
return \$data;
|
||||
}
|
||||
""";
|
||||
|
||||
//function to build formdata with 'file' type
|
||||
String kBuildFormDataFunctionWithFilesString = """
|
||||
function build_data_files(\$boundary, \$fields, \$files)
|
||||
{
|
||||
\$data = '';
|
||||
\$eol = "\\r\\n";
|
||||
|
||||
\$delimiter = '-------------' . \$boundary;
|
||||
|
||||
foreach (\$fields as \$name => \$content) {
|
||||
\$data .= "--" . \$delimiter . \$eol
|
||||
. 'Content-Disposition: form-data; name="' . \$name . "\\"" . \$eol . \$eol
|
||||
. \$content . \$eol;
|
||||
}
|
||||
|
||||
foreach (\$files as \$uploaded_file) {
|
||||
if (\$uploaded_file instanceof File) {
|
||||
\$data .= "--" . \$delimiter . \$eol
|
||||
. 'Content-Disposition: form-data; name="' . \$uploaded_file->name . '"; filename="' . \$uploaded_file->filename . '"' . \$eol
|
||||
. 'Content-Transfer-Encoding: binary' . \$eol;
|
||||
|
||||
\$data .= \$eol;
|
||||
\$data .= \$uploaded_file->content . \$eol;
|
||||
}
|
||||
}
|
||||
\$data .= "--" . \$delimiter . "--" . \$eol;
|
||||
|
||||
|
||||
return \$data;
|
||||
}
|
||||
|
||||
""";
|
||||
|
||||
//
|
||||
String kMultiPartBodyWithFiles = """
|
||||
\$request_body = build_data_files(\$boundary, \$fields, \$files);
|
||||
|
||||
""";
|
||||
|
||||
//
|
||||
String kMultiPartBodyWithoutFiles = """
|
||||
\$request_body = build_data(\$boundary, \$fields);
|
||||
|
||||
""";
|
||||
|
||||
String? getCode(RequestModel requestModel) {
|
||||
String uuid = getNewUuid();
|
||||
uuid = uuid.replaceAll(RegExp(r'-'), "");
|
||||
|
||||
try {
|
||||
String result = "";
|
||||
bool hasQuery = false;
|
||||
bool hasBody = false;
|
||||
|
||||
var rec = getValidRequestUri(
|
||||
requestModel.url,
|
||||
requestModel.enabledRequestParams,
|
||||
);
|
||||
|
||||
Uri? uri = rec.$1;
|
||||
|
||||
//renders starting template
|
||||
if (uri != null) {
|
||||
var templateStart = jj.Template(kTemplateStart);
|
||||
result += templateStart.render();
|
||||
|
||||
// if the request does not contain any file uploads, we do not need
|
||||
// to add the class for File in the request
|
||||
if (requestModel.hasFileInFormData) {
|
||||
result += kFileClassString;
|
||||
}
|
||||
|
||||
//adds the function to build formdata with or without 'file' type
|
||||
if (requestModel.hasFormData) {
|
||||
result += requestModel.hasFileInFormData
|
||||
? kBuildFormDataFunctionWithFilesString
|
||||
: kBuildFormDataFunctionWithoutFilesString;
|
||||
}
|
||||
|
||||
var templateUri = jj.Template(kTemplateUri);
|
||||
result += templateUri.render({"uri": requestModel.url});
|
||||
|
||||
//checking and adding query params
|
||||
if (uri.hasQuery) {
|
||||
var params = uri.queryParameters;
|
||||
if (params.isNotEmpty) {
|
||||
hasQuery = true;
|
||||
var templateParams = jj.Template(kTemplateParams);
|
||||
|
||||
// generating the map of key and value for the query parameters
|
||||
List<String> queryList = [];
|
||||
for (MapEntry<String, String> entry in params.entries) {
|
||||
String entryStr = "\"${entry.key}\" => \"${entry.value}\"";
|
||||
queryList.add(entryStr);
|
||||
}
|
||||
String paramsString = "\n ${queryList.join(",\n ")}\n";
|
||||
|
||||
result += templateParams.render({"params": paramsString});
|
||||
}
|
||||
}
|
||||
|
||||
// renders the initial request init function call
|
||||
var templateRequestInit = jj.Template(kTemplateRequestInit);
|
||||
result += templateRequestInit.render();
|
||||
|
||||
var harJson =
|
||||
requestModelToHARJsonRequest(requestModel, useEnabled: true);
|
||||
|
||||
var headers = harJson["headers"];
|
||||
|
||||
//parses and adds the headers
|
||||
if (headers.isNotEmpty || requestModel.hasFormData) {
|
||||
var templateHeader = jj.Template(kTemplateHeaders);
|
||||
var m = {};
|
||||
for (var i in headers) {
|
||||
m[i["name"]] = i["value"];
|
||||
}
|
||||
|
||||
if (requestModel.hasFormData) {
|
||||
// we will override any existing boundary and use our own boundary
|
||||
m[kHeaderContentType] =
|
||||
"${ContentType.formdata.header}; boundary=-------------$uuid";
|
||||
|
||||
var boundaryUniqueIdTemplate =
|
||||
jj.Template(kBoundaryUniqueIdTemplate);
|
||||
result += boundaryUniqueIdTemplate.render({"uuid": uuid});
|
||||
|
||||
var fieldsString = '\$fields = [\n';
|
||||
var filesString = '\$files = [\n';
|
||||
|
||||
for (var formData in requestModel.formDataMapList) {
|
||||
if (formData['type'] == 'text') {
|
||||
// the four spaces on the left hand side are for indentation, hence do not remove
|
||||
fieldsString +=
|
||||
' "${formData['name']}" => "${formData['value']}",\n';
|
||||
} else if (formData['type'] == 'file') {
|
||||
filesString +=
|
||||
' new File("${formData['name']}", "${formData['value']}"),\n';
|
||||
}
|
||||
}
|
||||
|
||||
fieldsString += '];\n';
|
||||
filesString += '];\n';
|
||||
|
||||
result += fieldsString;
|
||||
if (requestModel.hasFileInFormData) {
|
||||
result += filesString;
|
||||
|
||||
result += kMultiPartBodyWithFiles;
|
||||
} else {
|
||||
result += kMultiPartBodyWithoutFiles;
|
||||
}
|
||||
}
|
||||
|
||||
var headersString = '\n';
|
||||
m.forEach((key, value) {
|
||||
headersString += "\t\t\t\t'$key: $value', \n";
|
||||
});
|
||||
|
||||
result += templateHeader.render({
|
||||
"headers": headersString,
|
||||
});
|
||||
}
|
||||
|
||||
// contains the HTTP method associated with the request
|
||||
var method = requestModel.method;
|
||||
|
||||
// contains the entire request body as a string if body is present
|
||||
var requestBody = requestModel.requestBody;
|
||||
|
||||
//renders the request body
|
||||
if (kMethodsWithBody.contains(method) && requestBody != null) {
|
||||
var contentLength = utf8.encode(requestBody).length;
|
||||
if (contentLength > 0) {
|
||||
hasBody = true;
|
||||
var templateBody = jj.Template(kTemplateBody);
|
||||
result += templateBody.render({"body": requestBody});
|
||||
}
|
||||
}
|
||||
|
||||
//renders the request temlate
|
||||
var templateRequest = jj.Template(kTemplateRequest);
|
||||
result += templateRequest.render({
|
||||
"authority": uri.authority,
|
||||
"method": httpMethod(method.name.toUpperCase()),
|
||||
"path": uri.path,
|
||||
"queryParamsStr": hasQuery ? "queryParamsStr" : "",
|
||||
});
|
||||
|
||||
if (hasBody || requestModel.hasFormData) {
|
||||
result += kStringRequestBody;
|
||||
}
|
||||
|
||||
//and of the request
|
||||
result += kStringRequestEnd;
|
||||
}
|
||||
return result;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//function for http verb to curl mapping
|
||||
String httpMethod(String methodName) {
|
||||
switch (methodName) {
|
||||
case "POST":
|
||||
return "CURLOPT_POST";
|
||||
case "GET":
|
||||
return "CURLOPT_HTTPGET";
|
||||
case "PUT":
|
||||
return "CURLOPT_PUT";
|
||||
case "DELETE":
|
||||
return "CURLOPT_CUSTOMREQUEST";
|
||||
case "PATCH":
|
||||
return "CURLOPT_CUSTOMREQUEST";
|
||||
case "HEAD":
|
||||
return "CURLOPT_NOBODY";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
@ -107,7 +107,7 @@ echo \$res->getBody();
|
||||
headersString += "\t\t\t\t'$key' => '$value', \n";
|
||||
});
|
||||
if (requestModel.hasFormData) {
|
||||
m['Content-Type'] = 'multipart/form-data';
|
||||
m[kHeaderContentType] = ContentType.formdata.header;
|
||||
}
|
||||
headersString = headersString.substring(
|
||||
0, headersString.length - 2); // Removing trailing comma and space
|
||||
|
178
lib/codegen/ruby/faraday.dart
Normal file
178
lib/codegen/ruby/faraday.dart
Normal file
@ -0,0 +1,178 @@
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:jinja/jinja.dart' as jj;
|
||||
import 'package:apidash/utils/utils.dart' show getValidRequestUri;
|
||||
import 'package:apidash/utils/http_utils.dart' show stripUriParams;
|
||||
|
||||
import 'package:apidash/models/models.dart' show RequestModel;
|
||||
|
||||
// Note that delete is a special case in Faraday as API Dash supports request
|
||||
// body inside delete reqest, but Faraday does not. Hence we need to manually
|
||||
// setup request body for delete request and add that to request.
|
||||
//
|
||||
// Refer https://lostisland.github.io/faraday/#/getting-started/quick-start?id=get-head-delete-trace
|
||||
class RubyFaradayCodeGen {
|
||||
final String kStringFaradayRequireStatement = """
|
||||
require 'uri'
|
||||
require 'faraday'
|
||||
""";
|
||||
|
||||
final String kStringFaradayMultipartRequireStatement = '''
|
||||
require 'faraday/multipart'
|
||||
''';
|
||||
|
||||
final String kTemplateRequestUrl = """
|
||||
|
||||
REQUEST_URL = URI("{{ url }}")
|
||||
|
||||
|
||||
""";
|
||||
|
||||
final String kTemplateBody = """
|
||||
PAYLOAD = <<HEREDOC
|
||||
{{ body }}
|
||||
HEREDOC
|
||||
|
||||
|
||||
""";
|
||||
|
||||
final String kTemplateFormParamsWithFile = """
|
||||
PAYLOAD = {
|
||||
{% for param in params %}{% if param.type == "text" %} "{{ param.name }}" => Faraday::Multipart::ParamPart.new("{{ param.value }}", "text/plain"),
|
||||
{% elif param.type == "file" %} "{{ param.name }}" => Faraday::Multipart::FilePart.new("{{ param.value }}", "application/octet-stream"),{% endif %}{% endfor %}
|
||||
}
|
||||
|
||||
|
||||
""";
|
||||
|
||||
final String kTemplateFormParamsWithoutFile = """
|
||||
PAYLOAD = URI.encode_www_form({\n{% for param in params %} "{{ param.name }}" => "{{ param.value }}",\n{% endfor %}})\n\n
|
||||
""";
|
||||
|
||||
final String kTemplateConnection = """
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter{% if hasFile %}\n faraday.request :multipart{% endif %}
|
||||
end
|
||||
|
||||
|
||||
""";
|
||||
|
||||
final String kTemplateRequestStart = """
|
||||
response = conn.{{ method|lower }}(REQUEST_URL{% if doesMethodAcceptBody and containsBody %}, PAYLOAD{% endif %}) do |req|
|
||||
|
||||
""";
|
||||
|
||||
final String kTemplateRequestParams = """
|
||||
req.params = {
|
||||
{% for key, val in params %} "{{ key }}" => "{{ val }}",\n{% endfor %} }
|
||||
|
||||
""";
|
||||
|
||||
final String kTemplateRequestHeaders = """
|
||||
req.headers = {
|
||||
{% for key, val in headers %} "{{ key }}" => "{{ val }}",\n{% endfor %} }
|
||||
|
||||
""";
|
||||
|
||||
final String kStringDeleteRequestBody = """
|
||||
req.body = PAYLOAD
|
||||
""";
|
||||
|
||||
final String kStringRequestEnd = """
|
||||
end
|
||||
|
||||
""";
|
||||
|
||||
final String kStringResponse = """
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
|
||||
String? getCode(
|
||||
RequestModel requestModel,
|
||||
) {
|
||||
try {
|
||||
String result = "";
|
||||
|
||||
var rec = getValidRequestUri(
|
||||
requestModel.url,
|
||||
requestModel.enabledRequestParams,
|
||||
);
|
||||
|
||||
Uri? uri = rec.$1;
|
||||
|
||||
if (uri == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var url = stripUriParams(uri);
|
||||
|
||||
result += kStringFaradayRequireStatement;
|
||||
if (requestModel.hasFormDataContentType && requestModel.hasFileInFormData) {
|
||||
result += kStringFaradayMultipartRequireStatement;
|
||||
}
|
||||
|
||||
var templateRequestUrl = jj.Template(kTemplateRequestUrl);
|
||||
result += templateRequestUrl.render({"url": url});
|
||||
|
||||
if (requestModel.hasFormData) {
|
||||
jj.Template payload;
|
||||
if (requestModel.hasFileInFormData) {
|
||||
payload = jj.Template(kTemplateFormParamsWithFile);
|
||||
} else {
|
||||
payload = jj.Template(kTemplateFormParamsWithoutFile);
|
||||
}
|
||||
result += payload.render({"params": requestModel.formDataMapList});
|
||||
} else if (requestModel.hasJsonData || requestModel.hasTextData) {
|
||||
var templateBody = jj.Template(kTemplateBody);
|
||||
result += templateBody.render({
|
||||
"body": requestModel.requestBody,
|
||||
});
|
||||
}
|
||||
|
||||
// crreating faraday connection for request
|
||||
var templateConnection = jj.Template(kTemplateConnection);
|
||||
result += templateConnection.render({
|
||||
"hasFile": requestModel.hasFormDataContentType && requestModel.hasFileInFormData //
|
||||
});
|
||||
|
||||
// start of the request sending
|
||||
var templateRequestStart = jj.Template(kTemplateRequestStart);
|
||||
result += templateRequestStart.render({
|
||||
"method": requestModel.method.name,
|
||||
"doesMethodAcceptBody":
|
||||
kMethodsWithBody.contains(requestModel.method) && requestModel.method != HTTPVerb.delete, //
|
||||
"containsBody": requestModel.hasBody,
|
||||
});
|
||||
|
||||
var headers = requestModel.enabledHeadersMap;
|
||||
if (requestModel.hasBody && !requestModel.hasContentTypeHeader) {
|
||||
if (requestModel.hasJsonData || requestModel.hasTextData) {
|
||||
headers[kHeaderContentType] = requestModel.requestBodyContentType.header;
|
||||
}
|
||||
}
|
||||
|
||||
if (headers.isNotEmpty) {
|
||||
var templateRequestHeaders = jj.Template(kTemplateRequestHeaders);
|
||||
result += templateRequestHeaders.render({"headers": headers});
|
||||
}
|
||||
|
||||
if (uri.hasQuery) {
|
||||
var params = uri.queryParameters;
|
||||
if (params.isNotEmpty) {
|
||||
var templateRequestParams = jj.Template(kTemplateRequestParams);
|
||||
result += templateRequestParams.render({"params": params});
|
||||
}
|
||||
}
|
||||
|
||||
if (requestModel.hasBody && requestModel.method == HTTPVerb.delete) {
|
||||
result += kStringDeleteRequestBody;
|
||||
}
|
||||
|
||||
result += kStringRequestEnd;
|
||||
result += kStringResponse;
|
||||
return result;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:davi/davi.dart';
|
||||
|
||||
const kDiscordUrl = "https://bit.ly/heyfoss";
|
||||
const kGitUrl = "https://github.com/foss42/apidash";
|
||||
@ -21,7 +20,7 @@ final kIsLinux = !kIsWeb && Platform.isLinux;
|
||||
final kIsApple = !kIsWeb && (Platform.isIOS || Platform.isMacOS);
|
||||
final kIsDesktop =
|
||||
!kIsWeb && (Platform.isMacOS || Platform.isWindows || Platform.isLinux);
|
||||
|
||||
final kIsRunningTests = Platform.environment.containsKey('FLUTTER_TEST');
|
||||
final kIsIOS = !kIsWeb && Platform.isIOS;
|
||||
final kIsAndroid = !kIsWeb && Platform.isAndroid;
|
||||
final kIsMobile = !kIsWeb && (Platform.isIOS || Platform.isAndroid);
|
||||
@ -56,6 +55,7 @@ const kForegroundOpacity = 0.05;
|
||||
const kOverlayBackgroundOpacity = 0.5;
|
||||
|
||||
const kTextStyleButton = TextStyle(fontWeight: FontWeight.bold);
|
||||
const kTextStyleTab = TextStyle(fontSize: 14);
|
||||
const kTextStyleButtonSmall = TextStyle(fontSize: 12);
|
||||
const kFormDataButtonLabelTextStyle = TextStyle(
|
||||
fontSize: 12,
|
||||
@ -71,12 +71,18 @@ const kP5 = EdgeInsets.all(5);
|
||||
const kP8 = EdgeInsets.all(8);
|
||||
const kPs8 = EdgeInsets.only(left: 8);
|
||||
const kPs2 = EdgeInsets.only(left: 2);
|
||||
const kPe8 = EdgeInsets.only(right: 8.0);
|
||||
const kPh20v5 = EdgeInsets.symmetric(horizontal: 20, vertical: 5);
|
||||
const kPh20v10 = EdgeInsets.symmetric(horizontal: 20, vertical: 10);
|
||||
const kP10 = EdgeInsets.all(10);
|
||||
const kPv8 = EdgeInsets.symmetric(vertical: 8);
|
||||
const kPv2 = EdgeInsets.symmetric(vertical: 2);
|
||||
const kPh2 = EdgeInsets.symmetric(horizontal: 2);
|
||||
const kPt24o8 = EdgeInsets.only(top: 24, left: 8.0, right: 8.0, bottom: 8.0);
|
||||
const kPt5o10 =
|
||||
EdgeInsets.only(left: 10.0, right: 10.0, top: 5.0, bottom: 10.0);
|
||||
const kPh4 = EdgeInsets.symmetric(horizontal: 4);
|
||||
const kPh8 = EdgeInsets.symmetric(horizontal: 8);
|
||||
const kPh20 = EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
);
|
||||
@ -105,8 +111,6 @@ const kPb10 = EdgeInsets.only(
|
||||
const kPb15 = EdgeInsets.only(
|
||||
bottom: 15,
|
||||
);
|
||||
const kPr8CollectionPane = EdgeInsets.only(right: 8.0);
|
||||
const kpsV5 = EdgeInsets.symmetric(vertical: 2);
|
||||
const kHSpacer4 = SizedBox(width: 4);
|
||||
const kHSpacer5 = SizedBox(width: 5);
|
||||
const kHSpacer10 = SizedBox(width: 10);
|
||||
@ -118,26 +122,18 @@ const kVSpacer20 = SizedBox(height: 20);
|
||||
const kVSpacer40 = SizedBox(height: 40);
|
||||
|
||||
const kTabAnimationDuration = Duration(milliseconds: 200);
|
||||
const kTabHeight = 45.0;
|
||||
const kTabHeight = 32.0;
|
||||
const kHeaderHeight = 32.0;
|
||||
const kSegmentHeight = 24.0;
|
||||
const kTextButtonMinWidth = 44.0;
|
||||
|
||||
const kRandMax = 100000;
|
||||
|
||||
const kTableThemeData = DaviThemeData(
|
||||
columnDividerThickness: 1,
|
||||
columnDividerColor: kColorTransparent,
|
||||
row: RowThemeData(
|
||||
dividerColor: kColorTransparent,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(),
|
||||
),
|
||||
header: HeaderThemeData(
|
||||
visible: false,
|
||||
),
|
||||
const kDataTableScrollbarTheme = ScrollbarThemeData(
|
||||
crossAxisMargin: -4,
|
||||
);
|
||||
const kDataTableBottomPadding = 12.0;
|
||||
const kDataTableRowHeight = 36.0;
|
||||
|
||||
const kIconRemoveDark = Icon(
|
||||
Icons.remove_circle,
|
||||
@ -276,6 +272,7 @@ const kDefaultContentType = ContentType.json;
|
||||
enum CodegenLanguage {
|
||||
curl("cURL", "bash", "curl"),
|
||||
har("HAR", "json", "har"),
|
||||
cSharpRestSharp("C# (Rest Sharp)", "cs", "cs"),
|
||||
dartHttp("Dart (http)", "dart", "dart"),
|
||||
dartDio("Dart (dio)", "dart", "dart"),
|
||||
goHttp("Go (http)", "go", "go"),
|
||||
@ -286,6 +283,8 @@ enum CodegenLanguage {
|
||||
kotlinOkHttp("Kotlin (okhttp3)", "java", "kt"),
|
||||
pythonRequests("Python (requests)", "python", "py"),
|
||||
pythonHttpClient("Python (http.client)", "python", "py"),
|
||||
rubyFaraday("Ruby (Faraday)", "ruby", "rb"),
|
||||
rubyNetHttp("Ruby (Net::Http)", "Ruby", "rb"),
|
||||
rustActix("Rust (Actix Client)", "rust", "rs"),
|
||||
rustReqwest("Rust (reqwest)", "rust", "rs"),
|
||||
rustCurl("Rust (curl-rust)", "rust", "rs"),
|
||||
@ -295,7 +294,7 @@ enum CodegenLanguage {
|
||||
javaHttpClient("Java (HttpClient)", "java", "java"),
|
||||
juliaHttp("Julia (HTTP)", "julia", "jl"),
|
||||
phpGuzzle("PHP (guzzle)", "php", "php"),
|
||||
rubyNetHttp("Ruby (Net::Http)", "Ruby", "rb");
|
||||
phpCurl("PHP (curl)", "php", "php");
|
||||
|
||||
const CodegenLanguage(this.label, this.codeHighlightLang, this.ext);
|
||||
final String label;
|
||||
@ -401,7 +400,7 @@ const Map<String, Map<String, List<ResponseBodyView>>>
|
||||
kSubTypeDefaultViewOptions: kPreviewBodyViewOptions,
|
||||
},
|
||||
kTypeVideo: {
|
||||
kSubTypeDefaultViewOptions: kNoBodyViewOptions,
|
||||
kSubTypeDefaultViewOptions: kPreviewBodyViewOptions,
|
||||
},
|
||||
kTypeText: {
|
||||
kSubTypeDefaultViewOptions: kRawBodyViewOptions,
|
||||
@ -510,6 +509,9 @@ const kMimeTypeRaiseIssue =
|
||||
const kUnexpectedRaiseIssue =
|
||||
"\nIf the behaviour is unexpected, please raise an issue in API Dash GitHub repo so that we can resolve it.";
|
||||
|
||||
const kVideoError =
|
||||
"There seems to be an issue playing this video. Please raise an issue in API Dash GitHub repo so that we can resolve it.";
|
||||
|
||||
const kImageError =
|
||||
"There seems to be an issue rendering this image. Please raise an issue in API Dash GitHub repo so that we can resolve it.";
|
||||
|
||||
@ -538,3 +540,36 @@ const kLabelSave = "Save";
|
||||
const kLabelDownload = "Download";
|
||||
const kLabelSaving = "Saving";
|
||||
const kLabelSaved = "Saved";
|
||||
// Request Pane
|
||||
const kLabelRequest = "Request";
|
||||
const kLabelHideCode = "Hide Code";
|
||||
const kLabelViewCode = "View Code";
|
||||
const kLabelURLParams = "URL Params";
|
||||
const kLabelHeaders = "Headers";
|
||||
const kLabelBody = "Body";
|
||||
const kNameCheckbox = "Checkbox";
|
||||
const kNameURLParam = "URL Parameter";
|
||||
const kNameHeader = "Header Name";
|
||||
const kNameValue = "Value";
|
||||
const kNameField = "Field";
|
||||
const kHintAddURLParam = "Add URL Parameter";
|
||||
const kHintAddValue = "Add Value";
|
||||
const kHintAddName = "Add Name";
|
||||
const kHintAddFieldName = "Add Field Name";
|
||||
const kLabelAddParam = "Add Param";
|
||||
const kLabelAddHeader = "Add Header";
|
||||
const kLabelSelectFile = "Select File";
|
||||
const kLabelAddFormField = "Add Form Field";
|
||||
// Response Pane
|
||||
const kLabelNotSent = "Not Sent";
|
||||
const kLabelResponse = "Response";
|
||||
const kLabelResponseBody = "Response Body";
|
||||
const kTooltipClearResponse = "Clear Response";
|
||||
const kHeaderRow = ["Header Name", "Header Value"];
|
||||
const kLabelRequestHeaders = "Request Headers";
|
||||
const kLabelResponseHeaders = "Response Headers";
|
||||
const kLabelItems = "items";
|
||||
const kMsgError = "Error: Response data does not exist.";
|
||||
const kMsgNullBody = "Response body is missing (null).";
|
||||
const kMsgNoContent = "No content";
|
||||
const kMsgUnknowContentType = "Unknown Response Content-Type";
|
||||
|
1
lib/extensions/extensions.dart
Normal file
1
lib/extensions/extensions.dart
Normal file
@ -0,0 +1 @@
|
||||
export 'string_extensions.dart';
|
5
lib/extensions/string_extensions.dart
Normal file
5
lib/extensions/string_extensions.dart
Normal file
@ -0,0 +1,5 @@
|
||||
extension StringExtension on String {
|
||||
String capitalize() {
|
||||
return "${this[0].toUpperCase()}${substring(1).toLowerCase()}";
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ class RequestModel {
|
||||
this.message,
|
||||
this.responseModel,
|
||||
this.isWorking = false,
|
||||
this.sendingTime,
|
||||
});
|
||||
|
||||
final String id;
|
||||
@ -50,6 +51,7 @@ class RequestModel {
|
||||
final String? message;
|
||||
final ResponseModel? responseModel;
|
||||
final bool isWorking;
|
||||
final DateTime? sendingTime;
|
||||
|
||||
List<NameValueModel>? get enabledRequestHeaders =>
|
||||
getEnabledRows(requestHeaders, isHeaderEnabledList);
|
||||
@ -95,6 +97,7 @@ class RequestModel {
|
||||
RequestModel duplicate({
|
||||
required String id,
|
||||
String? name,
|
||||
int? requestTabIndex,
|
||||
}) {
|
||||
return RequestModel(
|
||||
id: id,
|
||||
@ -102,6 +105,7 @@ class RequestModel {
|
||||
url: url,
|
||||
name: name ?? "${this.name} (copy)",
|
||||
description: description,
|
||||
requestTabIndex: requestTabIndex ?? 0,
|
||||
requestHeaders: requestHeaders != null ? [...requestHeaders!] : null,
|
||||
requestParams: requestParams != null ? [...requestParams!] : null,
|
||||
isHeaderEnabledList:
|
||||
@ -133,6 +137,7 @@ class RequestModel {
|
||||
String? message,
|
||||
ResponseModel? responseModel,
|
||||
bool? isWorking,
|
||||
DateTime? sendingTime,
|
||||
}) {
|
||||
var headers = requestHeaders ?? this.requestHeaders;
|
||||
var params = requestParams ?? this.requestParams;
|
||||
@ -158,6 +163,7 @@ class RequestModel {
|
||||
message: message ?? this.message,
|
||||
responseModel: responseModel ?? this.responseModel,
|
||||
isWorking: isWorking ?? this.isWorking,
|
||||
sendingTime: sendingTime ?? this.sendingTime,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'settings_providers.dart';
|
||||
import 'ui_providers.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../consts.dart';
|
||||
import '../models/models.dart';
|
||||
import '../services/services.dart' show hiveHandler, HiveHandler, request;
|
||||
import '../utils/utils.dart' show getNewUuid, collectionToHAR;
|
||||
import '../consts.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'settings_providers.dart';
|
||||
import 'ui_providers.dart';
|
||||
|
||||
final selectedIdStateProvider = StateProvider<String?>((ref) => null);
|
||||
|
||||
@ -65,6 +66,7 @@ class CollectionStateNotifier
|
||||
.read(requestSequenceProvider.notifier)
|
||||
.update((state) => [id, ...state]);
|
||||
ref.read(selectedIdStateProvider.notifier).state = newRequestModel.id;
|
||||
ref.read(hasUnsavedChangesProvider.notifier).state = true;
|
||||
}
|
||||
|
||||
void reorder(int oldIdx, int newIdx) {
|
||||
@ -72,6 +74,7 @@ class CollectionStateNotifier
|
||||
final itemId = itemIds.removeAt(oldIdx);
|
||||
itemIds.insert(newIdx, itemId);
|
||||
ref.read(requestSequenceProvider.notifier).state = [...itemIds];
|
||||
ref.read(hasUnsavedChangesProvider.notifier).state = true;
|
||||
}
|
||||
|
||||
void remove(String id) {
|
||||
@ -94,6 +97,7 @@ class CollectionStateNotifier
|
||||
var map = {...state!};
|
||||
map.remove(id);
|
||||
state = map;
|
||||
ref.read(hasUnsavedChangesProvider.notifier).state = true;
|
||||
}
|
||||
|
||||
void clearResponse(String? id) {
|
||||
@ -102,10 +106,12 @@ class CollectionStateNotifier
|
||||
final newModel = currentModel.duplicate(
|
||||
id: id,
|
||||
name: currentModel.name,
|
||||
requestTabIndex: currentModel.requestTabIndex,
|
||||
);
|
||||
var map = {...state!};
|
||||
map[id] = newModel;
|
||||
state = map;
|
||||
ref.read(hasUnsavedChangesProvider.notifier).state = true;
|
||||
}
|
||||
|
||||
void duplicate(String id) {
|
||||
@ -125,6 +131,7 @@ class CollectionStateNotifier
|
||||
|
||||
ref.read(requestSequenceProvider.notifier).state = [...itemIds];
|
||||
ref.read(selectedIdStateProvider.notifier).state = newId;
|
||||
ref.read(hasUnsavedChangesProvider.notifier).state = true;
|
||||
}
|
||||
|
||||
void update(
|
||||
@ -166,6 +173,7 @@ class CollectionStateNotifier
|
||||
var map = {...state!};
|
||||
map[id] = newModel;
|
||||
state = map;
|
||||
ref.read(hasUnsavedChangesProvider.notifier).state = true;
|
||||
}
|
||||
|
||||
Future<void> sendRequest(String id) async {
|
||||
@ -180,7 +188,10 @@ class CollectionStateNotifier
|
||||
|
||||
// set current model's isWorking to true and update state
|
||||
var map = {...state!};
|
||||
map[id] = requestModel.copyWith(isWorking: true);
|
||||
map[id] = requestModel.copyWith(
|
||||
isWorking: true,
|
||||
sendingTime: DateTime.now(),
|
||||
);
|
||||
state = map;
|
||||
|
||||
(http.Response?, Duration?, String?)? responseRec = await request(
|
||||
@ -212,6 +223,7 @@ class CollectionStateNotifier
|
||||
map = {...state!};
|
||||
map[id] = newRequestModel;
|
||||
state = map;
|
||||
ref.read(hasUnsavedChangesProvider.notifier).state = true;
|
||||
}
|
||||
|
||||
Future<void> clearData() async {
|
||||
@ -221,6 +233,7 @@ class CollectionStateNotifier
|
||||
ref.read(clearDataStateProvider.notifier).state = false;
|
||||
ref.read(requestSequenceProvider.notifier).state = [];
|
||||
state = {};
|
||||
ref.read(hasUnsavedChangesProvider.notifier).state = true;
|
||||
}
|
||||
|
||||
bool loadData() {
|
||||
@ -261,6 +274,7 @@ class CollectionStateNotifier
|
||||
}
|
||||
await hiveHandler.removeUnused();
|
||||
ref.read(saveDataStateProvider.notifier).state = false;
|
||||
ref.read(hasUnsavedChangesProvider.notifier).state = false;
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> exportDataToHAR() async {
|
||||
|
@ -6,6 +6,8 @@ final selectedIdEditStateProvider = StateProvider<String?>((ref) => null);
|
||||
final codePaneVisibleStateProvider = StateProvider<bool>((ref) => false);
|
||||
final saveDataStateProvider = StateProvider<bool>((ref) => false);
|
||||
final clearDataStateProvider = StateProvider<bool>((ref) => false);
|
||||
final hasUnsavedChangesProvider = StateProvider<bool>((ref) => false);
|
||||
|
||||
// final nameTextFieldControllerProvider =
|
||||
// StateProvider.autoDispose<TextEditingController>((ref) {
|
||||
// TextEditingController controller = TextEditingController(text: "");
|
||||
@ -23,3 +25,5 @@ final nameTextFieldFocusNodeProvider =
|
||||
});
|
||||
return focusNode;
|
||||
});
|
||||
|
||||
final searchQueryProvider = StateProvider<String>((ref) => '');
|
||||
|
@ -15,6 +15,7 @@ class CollectionPane extends ConsumerWidget {
|
||||
final overlayWidget = OverlayWidgetTemplate(context: context);
|
||||
final collection = ref.watch(collectionStateNotifierProvider);
|
||||
final savingData = ref.watch(saveDataStateProvider);
|
||||
final hasUnsavedChanges = ref.watch(hasUnsavedChangesProvider);
|
||||
if (collection == null) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
@ -26,12 +27,12 @@ class CollectionPane extends ConsumerWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(
|
||||
padding: kPr8CollectionPane,
|
||||
padding: kPe8,
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
children: [
|
||||
TextButton.icon(
|
||||
onPressed: savingData
|
||||
onPressed: (savingData || !hasUnsavedChanges)
|
||||
? null
|
||||
: () async {
|
||||
overlayWidget.show(
|
||||
@ -69,7 +70,39 @@ class CollectionPane extends ConsumerWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
kVSpacer8,
|
||||
kVSpacer10,
|
||||
Container(
|
||||
height: 30,
|
||||
margin: const EdgeInsets.only(right: 8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: kBorderRadius8,
|
||||
border: Border.all(
|
||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
kHSpacer5,
|
||||
Icon(
|
||||
Icons.filter_alt,
|
||||
size: 18,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
kHSpacer5,
|
||||
Expanded(
|
||||
child: RawTextField(
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
hintText: "Filter by name or URL",
|
||||
onChanged: (value) {
|
||||
ref.read(searchQueryProvider.notifier).state =
|
||||
value.toLowerCase();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
kVSpacer10,
|
||||
const Expanded(
|
||||
child: RequestList(),
|
||||
),
|
||||
@ -109,13 +142,15 @@ class _RequestListState extends ConsumerState<RequestList> {
|
||||
final requestItems = ref.watch(collectionStateNotifierProvider)!;
|
||||
final alwaysShowCollectionPaneScrollbar = ref.watch(settingsProvider
|
||||
.select((value) => value.alwaysShowCollectionPaneScrollbar));
|
||||
final filterQuery = ref.watch(searchQueryProvider).trim();
|
||||
|
||||
return Scrollbar(
|
||||
controller: controller,
|
||||
thumbVisibility: alwaysShowCollectionPaneScrollbar ? true : null,
|
||||
radius: const Radius.circular(12),
|
||||
child: ReorderableListView.builder(
|
||||
padding: kPr8CollectionPane,
|
||||
child: filterQuery.isEmpty
|
||||
? ReorderableListView.builder(
|
||||
padding: kPe8,
|
||||
scrollController: controller,
|
||||
buildDefaultDragHandles: false,
|
||||
itemCount: requestSequence.length,
|
||||
@ -143,6 +178,24 @@ class _RequestListState extends ConsumerState<RequestList> {
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: ListView(
|
||||
padding: kPe8,
|
||||
controller: controller,
|
||||
children: requestSequence.map((id) {
|
||||
var item = requestItems[id]!;
|
||||
if (item.url.toLowerCase().contains(filterQuery) ||
|
||||
item.name.toLowerCase().contains(filterQuery)) {
|
||||
return Padding(
|
||||
padding: kP1,
|
||||
child: RequestItem(
|
||||
id: id,
|
||||
requestModel: item,
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SizedBox();
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ class EditRequestBody extends ConsumerWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
),
|
||||
margin: kPt5o10,
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
@ -38,9 +37,12 @@ class EditRequestBody extends ConsumerWidget {
|
||||
),
|
||||
Expanded(
|
||||
child: switch (contentType) {
|
||||
ContentType.formdata => const FormDataWidget(),
|
||||
ContentType.formdata =>
|
||||
const Padding(padding: kPh4, child: FormDataWidget()),
|
||||
// TODO: Fix JsonTextFieldEditor & plug it here
|
||||
ContentType.json => TextFieldEditor(
|
||||
ContentType.json => Padding(
|
||||
padding: kPt5o10,
|
||||
child: TextFieldEditor(
|
||||
key: Key("$selectedId-json-body"),
|
||||
fieldKey: "$selectedId-json-body-editor",
|
||||
initialValue: requestModel?.requestBody,
|
||||
@ -50,7 +52,10 @@ class EditRequestBody extends ConsumerWidget {
|
||||
.update(selectedId, requestBody: value);
|
||||
},
|
||||
),
|
||||
_ => TextFieldEditor(
|
||||
),
|
||||
_ => Padding(
|
||||
padding: kPt5o10,
|
||||
child: TextFieldEditor(
|
||||
key: Key("$selectedId-body"),
|
||||
fieldKey: "$selectedId-body-editor",
|
||||
initialValue: requestModel?.requestBody,
|
||||
@ -60,6 +65,7 @@ class EditRequestBody extends ConsumerWidget {
|
||||
.update(selectedId, requestBody: value);
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
)
|
||||
],
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:davi/davi.dart';
|
||||
import 'package:data_table_2/data_table_2.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'package:apidash/widgets/widgets.dart';
|
||||
import 'package:apidash/models/models.dart';
|
||||
@ -18,6 +18,7 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
late int seed;
|
||||
final random = Random.secure();
|
||||
late List<FormDataModel> formRows;
|
||||
bool isAddingRow = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -39,159 +40,163 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
.select((value) => value?.requestFormDataList?.length));
|
||||
var rF = ref.read(selectedRequestModelProvider)?.requestFormDataList;
|
||||
bool isFormDataEmpty = rF == null || rF.isEmpty;
|
||||
List<FormDataModel> rows = (isFormDataEmpty)
|
||||
formRows = isFormDataEmpty
|
||||
? [
|
||||
kFormDataEmptyModel,
|
||||
]
|
||||
: rF;
|
||||
formRows = isFormDataEmpty ? rows : rows + [kFormDataEmptyModel];
|
||||
: rF +
|
||||
[
|
||||
kFormDataEmptyModel,
|
||||
];
|
||||
isAddingRow = false;
|
||||
|
||||
DaviModel<FormDataModel> daviModelRows = DaviModel<FormDataModel>(
|
||||
rows: formRows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
cellPadding: kpsV5,
|
||||
name: 'Key',
|
||||
grow: 4,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == formRows.length;
|
||||
return Theme(
|
||||
data: Theme.of(context),
|
||||
child: FormDataField(
|
||||
keyId: "$selectedId-$idx-form-v-$seed",
|
||||
initialValue: formRows[idx].name,
|
||||
hintText: " Add Key",
|
||||
List<DataColumn> columns = const [
|
||||
DataColumn2(
|
||||
label: Text(kNameField),
|
||||
size: ColumnSize.M,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text('='),
|
||||
fixedWidth: 20,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(''),
|
||||
fixedWidth: 70,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(kNameValue),
|
||||
size: ColumnSize.L,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(''),
|
||||
fixedWidth: 32,
|
||||
),
|
||||
];
|
||||
|
||||
List<DataRow> dataRows = List<DataRow>.generate(
|
||||
formRows.length,
|
||||
(index) {
|
||||
bool isLast = index + 1 == formRows.length;
|
||||
return DataRow(
|
||||
key: ValueKey("$selectedId-$index-form-row-$seed"),
|
||||
cells: <DataCell>[
|
||||
DataCell(
|
||||
CellField(
|
||||
keyId: "$selectedId-$index-form-k-$seed",
|
||||
initialValue: formRows[index].name,
|
||||
hintText: kHintAddFieldName,
|
||||
onChanged: (value) {
|
||||
formRows[idx] = formRows[idx].copyWith(name: value);
|
||||
if (isLast) formRows.add(kFormDataEmptyModel);
|
||||
formRows[index] = formRows[index].copyWith(name: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
formRows.add(kFormDataEmptyModel);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
formDataType: formRows[idx].type,
|
||||
onFormDataTypeChanged: (value) {
|
||||
bool hasChanged = formRows[idx].type != value;
|
||||
formRows[idx] = formRows[idx].copyWith(
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
Center(
|
||||
child: Text(
|
||||
"=",
|
||||
style: kCodeStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
DropdownButtonFormData(
|
||||
formDataType: formRows[index].type,
|
||||
onChanged: (value) {
|
||||
bool hasChanged = formRows[index].type != value;
|
||||
formRows[index] = formRows[index].copyWith(
|
||||
type: value ?? FormDataType.text,
|
||||
);
|
||||
formRows[idx] = formRows[idx].copyWith(value: "");
|
||||
if (idx == formRows.length - 1 && hasChanged) {
|
||||
formRows[index] = formRows[index].copyWith(value: "");
|
||||
if (isLast && hasChanged) {
|
||||
formRows.add(kFormDataEmptyModel);
|
||||
}
|
||||
setState(() {});
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
width: 40,
|
||||
cellPadding: kpsV5,
|
||||
cellAlignment: Alignment.center,
|
||||
cellBuilder: (_, row) {
|
||||
return Text(
|
||||
"=",
|
||||
style: kCodeStyle,
|
||||
);
|
||||
},
|
||||
),
|
||||
DaviColumn(
|
||||
name: 'Value',
|
||||
grow: 4,
|
||||
cellPadding: kpsV5,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == formRows.length;
|
||||
return formRows[idx].type == FormDataType.file
|
||||
? Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Theme(
|
||||
data: Theme.of(context),
|
||||
child: ElevatedButton.icon(
|
||||
DataCell(
|
||||
formRows[index].type == FormDataType.file
|
||||
? ElevatedButton.icon(
|
||||
icon: const Icon(
|
||||
Icons.snippet_folder_rounded,
|
||||
size: 20,
|
||||
),
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStatePropertyAll(
|
||||
RoundedRectangleBorder(
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: const Size.fromHeight(kDataTableRowHeight),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
),
|
||||
),
|
||||
onPressed: () async {
|
||||
var pickedResult = await pickFile();
|
||||
if (pickedResult != null &&
|
||||
pickedResult.files.isNotEmpty &&
|
||||
pickedResult.files.first.path != null) {
|
||||
formRows[idx] = formRows[idx].copyWith(
|
||||
value: pickedResult.files.first.path!,
|
||||
pickedResult.path.isNotEmpty) {
|
||||
formRows[index] = formRows[index].copyWith(
|
||||
value: pickedResult.path,
|
||||
);
|
||||
setState(() {});
|
||||
_onFieldChange(selectedId!);
|
||||
}
|
||||
},
|
||||
label: Text(
|
||||
(formRows[idx].type == FormDataType.file &&
|
||||
formRows[idx].value.isNotEmpty)
|
||||
? formRows[idx].value.toString()
|
||||
: "Select File",
|
||||
textAlign: TextAlign.center,
|
||||
(formRows[index].type == FormDataType.file &&
|
||||
formRows[index].value.isNotEmpty)
|
||||
? formRows[index].value.toString()
|
||||
: kLabelSelectFile,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: kFormDataButtonLabelTextStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: CellField(
|
||||
keyId: "$selectedId-$idx-form-v-$seed",
|
||||
initialValue: formRows[idx].value,
|
||||
hintText: " Add Value",
|
||||
keyId: "$selectedId-$index-form-v-$seed",
|
||||
initialValue: formRows[index].value,
|
||||
hintText: kHintAddValue,
|
||||
onChanged: (value) {
|
||||
formRows[idx] = formRows[idx].copyWith(value: value);
|
||||
if (isLast) formRows.add(kFormDataEmptyModel);
|
||||
formRows[index] =
|
||||
formRows[index].copyWith(value: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
formRows.add(kFormDataEmptyModel);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
pinStatus: PinStatus.none,
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
bool isLast = row.index + 1 == formRows.length;
|
||||
return InkWell(
|
||||
),
|
||||
DataCell(
|
||||
InkWell(
|
||||
onTap: isLast
|
||||
? null
|
||||
: () {
|
||||
seed = random.nextInt(kRandMax);
|
||||
if (formRows.length == 2) {
|
||||
setState(() {
|
||||
formRows = [kFormDataEmptyModel];
|
||||
formRows = [
|
||||
kFormDataEmptyModel,
|
||||
];
|
||||
});
|
||||
} else {
|
||||
formRows.removeAt(row.index);
|
||||
formRows.removeAt(index);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
child: Theme.of(context).brightness == Brightness.dark
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
@ -203,19 +208,30 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: kTableThemeData,
|
||||
child: Davi<FormDataModel>(daviModelRows),
|
||||
child: Theme(
|
||||
data: Theme.of(context)
|
||||
.copyWith(scrollbarTheme: kDataTableScrollbarTheme),
|
||||
child: DataTable2(
|
||||
columnSpacing: 12,
|
||||
dividerThickness: 0,
|
||||
horizontalMargin: 0,
|
||||
headingRowHeight: 0,
|
||||
dataRowHeight: kDataTableRowHeight,
|
||||
bottomMargin: kDataTableBottomPadding,
|
||||
isVerticalScrollBarVisible: true,
|
||||
columns: columns,
|
||||
rows: dataRows,
|
||||
),
|
||||
),
|
||||
kVSpacer20,
|
||||
),
|
||||
kVSpacer40,
|
||||
],
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 5),
|
||||
padding: kPb15,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
formRows.add(kFormDataEmptyModel);
|
||||
@ -223,7 +239,7 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text(
|
||||
"Add Form Data",
|
||||
kLabelAddFormField,
|
||||
style: kTextStyleButton,
|
||||
),
|
||||
),
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:davi/davi.dart';
|
||||
import 'package:data_table_2/data_table_2.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'package:apidash/widgets/widgets.dart';
|
||||
import 'package:apidash/models/models.dart';
|
||||
@ -19,6 +19,7 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
final random = Random.secure();
|
||||
late List<NameValueModel> headerRows;
|
||||
late List<bool> isRowEnabledList;
|
||||
bool isAddingRow = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -42,105 +43,106 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
.select((value) => value?.requestHeaders?.length));
|
||||
var rH = ref.read(selectedRequestModelProvider)?.requestHeaders;
|
||||
bool isHeadersEmpty = rH == null || rH.isEmpty;
|
||||
List<NameValueModel> rows = (isHeadersEmpty)
|
||||
headerRows = isHeadersEmpty
|
||||
? [
|
||||
kNameValueEmptyModel,
|
||||
]
|
||||
: rH;
|
||||
headerRows = isHeadersEmpty ? rows : rows + [kNameValueEmptyModel];
|
||||
: rH + [kNameValueEmptyModel];
|
||||
isRowEnabledList =
|
||||
ref.read(selectedRequestModelProvider)?.isHeaderEnabledList ??
|
||||
List.filled(rH?.length ?? 0, true, growable: true);
|
||||
isRowEnabledList.add(false);
|
||||
isAddingRow = false;
|
||||
|
||||
DaviModel<NameValueModel> model = DaviModel<NameValueModel>(
|
||||
rows: headerRows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
name: 'Checkbox',
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == headerRows.length;
|
||||
return CheckBox(
|
||||
keyId: "$selectedId-$idx-headers-c-$seed",
|
||||
value: isRowEnabledList[idx],
|
||||
List<DataColumn> columns = const [
|
||||
DataColumn2(
|
||||
label: Text(kNameCheckbox),
|
||||
fixedWidth: 30,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(kNameHeader),
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text('='),
|
||||
fixedWidth: 30,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(kNameValue),
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(''),
|
||||
fixedWidth: 32,
|
||||
),
|
||||
];
|
||||
|
||||
List<DataRow> dataRows = List<DataRow>.generate(
|
||||
headerRows.length,
|
||||
(index) {
|
||||
bool isLast = index + 1 == headerRows.length;
|
||||
return DataRow(
|
||||
key: ValueKey("$selectedId-$index-headers-row-$seed"),
|
||||
cells: <DataCell>[
|
||||
DataCell(
|
||||
CheckBox(
|
||||
keyId: "$selectedId-$index-headers-c-$seed",
|
||||
value: isRowEnabledList[index],
|
||||
onChanged: isLast
|
||||
? null
|
||||
: (value) {
|
||||
setState(() {
|
||||
isRowEnabledList[idx] = value!;
|
||||
isRowEnabledList[index] = value!;
|
||||
});
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
),
|
||||
DaviColumn(
|
||||
name: 'Header Name',
|
||||
width: 70,
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == headerRows.length;
|
||||
return HeaderField(
|
||||
keyId: "$selectedId-$idx-headers-k-$seed",
|
||||
initialValue: headerRows[idx].name,
|
||||
hintText: "Add Header Name",
|
||||
),
|
||||
DataCell(
|
||||
HeaderField(
|
||||
keyId: "$selectedId-$index-headers-k-$seed",
|
||||
initialValue: headerRows[index].name,
|
||||
hintText: kHintAddName,
|
||||
onChanged: (value) {
|
||||
headerRows[idx] = headerRows[idx].copyWith(name: value);
|
||||
if (isLast) {
|
||||
isRowEnabledList[idx] = true;
|
||||
headerRows[index] = headerRows[index].copyWith(name: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
isRowEnabledList[index] = true;
|
||||
headerRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
return Text(
|
||||
),
|
||||
DataCell(
|
||||
Center(
|
||||
child: Text(
|
||||
"=",
|
||||
style: kCodeStyle,
|
||||
);
|
||||
},
|
||||
),
|
||||
DaviColumn(
|
||||
name: 'Header Value',
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == headerRows.length;
|
||||
return CellField(
|
||||
keyId: "$selectedId-$idx-headers-v-$seed",
|
||||
initialValue: headerRows[idx].value,
|
||||
hintText: " Add Header Value",
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
CellField(
|
||||
keyId: "$selectedId-$index-headers-v-$seed",
|
||||
initialValue: headerRows[index].value,
|
||||
hintText: kHintAddValue,
|
||||
onChanged: (value) {
|
||||
headerRows[idx] = headerRows[idx].copyWith(value: value);
|
||||
if (isLast) {
|
||||
isRowEnabledList[idx] = true;
|
||||
headerRows[index] = headerRows[index].copyWith(value: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
isRowEnabledList[index] = true;
|
||||
headerRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
pinStatus: PinStatus.none,
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
bool isLast = row.index + 1 == headerRows.length;
|
||||
return InkWell(
|
||||
),
|
||||
DataCell(
|
||||
InkWell(
|
||||
onTap: isLast
|
||||
? null
|
||||
: () {
|
||||
@ -153,19 +155,21 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
isRowEnabledList = [false];
|
||||
});
|
||||
} else {
|
||||
headerRows.removeAt(row.index);
|
||||
isRowEnabledList.removeAt(row.index);
|
||||
headerRows.removeAt(index);
|
||||
isRowEnabledList.removeAt(index);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
child: Theme.of(context).brightness == Brightness.dark
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
@ -177,9 +181,20 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: kTableThemeData,
|
||||
child: Davi<NameValueModel>(model),
|
||||
child: Theme(
|
||||
data: Theme.of(context)
|
||||
.copyWith(scrollbarTheme: kDataTableScrollbarTheme),
|
||||
child: DataTable2(
|
||||
columnSpacing: 12,
|
||||
dividerThickness: 0,
|
||||
horizontalMargin: 0,
|
||||
headingRowHeight: 0,
|
||||
dataRowHeight: kDataTableRowHeight,
|
||||
bottomMargin: kDataTableBottomPadding,
|
||||
isVerticalScrollBarVisible: true,
|
||||
columns: columns,
|
||||
rows: dataRows,
|
||||
),
|
||||
),
|
||||
),
|
||||
kVSpacer40,
|
||||
@ -198,7 +213,7 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text(
|
||||
"Add Header",
|
||||
kLabelAddHeader,
|
||||
style: kTextStyleButton,
|
||||
),
|
||||
),
|
||||
|
@ -1,11 +1,11 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:davi/davi.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'package:apidash/widgets/widgets.dart';
|
||||
import 'package:apidash/models/models.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:data_table_2/data_table_2.dart';
|
||||
|
||||
class EditRequestURLParams extends ConsumerStatefulWidget {
|
||||
const EditRequestURLParams({super.key});
|
||||
@ -20,6 +20,7 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
final random = Random.secure();
|
||||
late List<NameValueModel> paramRows;
|
||||
late List<bool> isRowEnabledList;
|
||||
bool isAddingRow = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -42,105 +43,106 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
.select((value) => value?.requestParams?.length));
|
||||
var rP = ref.read(selectedRequestModelProvider)?.requestParams;
|
||||
bool isParamsEmpty = rP == null || rP.isEmpty;
|
||||
List<NameValueModel> rows = (isParamsEmpty)
|
||||
paramRows = isParamsEmpty
|
||||
? [
|
||||
kNameValueEmptyModel,
|
||||
]
|
||||
: rP;
|
||||
paramRows = isParamsEmpty ? rows : rows + [kNameValueEmptyModel];
|
||||
: rP + [kNameValueEmptyModel];
|
||||
isRowEnabledList =
|
||||
ref.read(selectedRequestModelProvider)?.isParamEnabledList ??
|
||||
List.filled(rP?.length ?? 0, true, growable: true);
|
||||
isRowEnabledList.add(false);
|
||||
isAddingRow = false;
|
||||
|
||||
DaviModel<NameValueModel> model = DaviModel<NameValueModel>(
|
||||
rows: paramRows,
|
||||
columns: [
|
||||
DaviColumn(
|
||||
name: 'Checkbox',
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == paramRows.length;
|
||||
return CheckBox(
|
||||
keyId: "$selectedId-$idx-params-c-$seed",
|
||||
value: isRowEnabledList[idx],
|
||||
List<DataColumn> columns = const [
|
||||
DataColumn2(
|
||||
label: Text(kNameCheckbox),
|
||||
fixedWidth: 30,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(kNameURLParam),
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text('='),
|
||||
fixedWidth: 30,
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(kNameValue),
|
||||
),
|
||||
DataColumn2(
|
||||
label: Text(''),
|
||||
fixedWidth: 32,
|
||||
),
|
||||
];
|
||||
|
||||
List<DataRow> dataRows = List<DataRow>.generate(
|
||||
paramRows.length,
|
||||
(index) {
|
||||
bool isLast = index + 1 == paramRows.length;
|
||||
return DataRow(
|
||||
key: ValueKey("$selectedId-$index-params-row-$seed"),
|
||||
cells: <DataCell>[
|
||||
DataCell(
|
||||
CheckBox(
|
||||
keyId: "$selectedId-$index-params-c-$seed",
|
||||
value: isRowEnabledList[index],
|
||||
onChanged: isLast
|
||||
? null
|
||||
: (value) {
|
||||
setState(() {
|
||||
isRowEnabledList[idx] = value!;
|
||||
isRowEnabledList[index] = value!;
|
||||
});
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
),
|
||||
DaviColumn(
|
||||
name: 'URL Parameter',
|
||||
width: 70,
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == paramRows.length;
|
||||
return CellField(
|
||||
keyId: "$selectedId-$idx-params-k-$seed",
|
||||
initialValue: paramRows[idx].name,
|
||||
hintText: "Add URL Parameter",
|
||||
),
|
||||
DataCell(
|
||||
CellField(
|
||||
keyId: "$selectedId-$index-params-k-$seed",
|
||||
initialValue: paramRows[index].name,
|
||||
hintText: kHintAddURLParam,
|
||||
onChanged: (value) {
|
||||
paramRows[idx] = paramRows[idx].copyWith(name: value);
|
||||
if (isLast) {
|
||||
isRowEnabledList[idx] = true;
|
||||
paramRows[index] = paramRows[index].copyWith(name: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
isRowEnabledList[index] = true;
|
||||
paramRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
return Text(
|
||||
),
|
||||
DataCell(
|
||||
Center(
|
||||
child: Text(
|
||||
"=",
|
||||
style: kCodeStyle,
|
||||
);
|
||||
},
|
||||
),
|
||||
DaviColumn(
|
||||
name: 'Value',
|
||||
grow: 1,
|
||||
cellBuilder: (_, row) {
|
||||
int idx = row.index;
|
||||
bool isLast = idx + 1 == paramRows.length;
|
||||
return CellField(
|
||||
keyId: "$selectedId-$idx-params-v-$seed",
|
||||
initialValue: paramRows[idx].value,
|
||||
hintText: "Add Value",
|
||||
),
|
||||
),
|
||||
DataCell(
|
||||
CellField(
|
||||
keyId: "$selectedId-$index-params-v-$seed",
|
||||
initialValue: paramRows[index].value,
|
||||
hintText: kHintAddValue,
|
||||
onChanged: (value) {
|
||||
paramRows[idx] = paramRows[idx].copyWith(value: value);
|
||||
if (isLast) {
|
||||
isRowEnabledList[idx] = true;
|
||||
paramRows[index] = paramRows[index].copyWith(value: value);
|
||||
if (isLast && !isAddingRow) {
|
||||
isAddingRow = true;
|
||||
isRowEnabledList[index] = true;
|
||||
paramRows.add(kNameValueEmptyModel);
|
||||
isRowEnabledList.add(false);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
);
|
||||
},
|
||||
sortable: false,
|
||||
),
|
||||
DaviColumn(
|
||||
pinStatus: PinStatus.none,
|
||||
width: 30,
|
||||
cellBuilder: (_, row) {
|
||||
bool isLast = row.index + 1 == paramRows.length;
|
||||
return InkWell(
|
||||
),
|
||||
DataCell(
|
||||
InkWell(
|
||||
onTap: isLast
|
||||
? null
|
||||
: () {
|
||||
@ -153,19 +155,21 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
isRowEnabledList = [false];
|
||||
});
|
||||
} else {
|
||||
paramRows.removeAt(row.index);
|
||||
isRowEnabledList.removeAt(row.index);
|
||||
paramRows.removeAt(index);
|
||||
isRowEnabledList.removeAt(index);
|
||||
}
|
||||
_onFieldChange(selectedId!);
|
||||
},
|
||||
child: Theme.of(context).brightness == Brightness.dark
|
||||
? kIconRemoveDark
|
||||
: kIconRemoveLight,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
@ -175,11 +179,23 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
),
|
||||
margin: kP10,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: DaviTheme(
|
||||
data: kTableThemeData,
|
||||
child: Davi<NameValueModel>(model),
|
||||
child: Theme(
|
||||
data: Theme.of(context)
|
||||
.copyWith(scrollbarTheme: kDataTableScrollbarTheme),
|
||||
child: DataTable2(
|
||||
columnSpacing: 12,
|
||||
dividerThickness: 0,
|
||||
horizontalMargin: 0,
|
||||
headingRowHeight: 0,
|
||||
dataRowHeight: kDataTableRowHeight,
|
||||
bottomMargin: kDataTableBottomPadding,
|
||||
isVerticalScrollBarVisible: true,
|
||||
columns: columns,
|
||||
rows: dataRows,
|
||||
),
|
||||
),
|
||||
),
|
||||
kVSpacer40,
|
||||
@ -198,7 +214,7 @@ class EditRequestURLParamsState extends ConsumerState<EditRequestURLParams> {
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text(
|
||||
"Add Param",
|
||||
kLabelAddParam,
|
||||
style: kTextStyleButton,
|
||||
),
|
||||
),
|
||||
|
@ -12,12 +12,17 @@ class ResponsePane extends ConsumerWidget {
|
||||
final isWorking = ref.watch(
|
||||
selectedRequestModelProvider.select((value) => value?.isWorking)) ??
|
||||
false;
|
||||
final startSendingTime = ref.watch(
|
||||
selectedRequestModelProvider.select((value) => value?.sendingTime));
|
||||
final responseStatus = ref.watch(
|
||||
selectedRequestModelProvider.select((value) => value?.responseStatus));
|
||||
final message = ref
|
||||
.watch(selectedRequestModelProvider.select((value) => value?.message));
|
||||
|
||||
if (isWorking) {
|
||||
return const SendingWidget();
|
||||
return SendingWidget(
|
||||
startSendingTime: startSendingTime,
|
||||
);
|
||||
}
|
||||
if (responseStatus == null) {
|
||||
return const NotSentWidget();
|
||||
@ -34,7 +39,6 @@ class ResponseDetails extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
var sm = ScaffoldMessenger.of(context);
|
||||
final responseStatus = ref.watch(
|
||||
selectedRequestModelProvider.select((value) => value?.responseStatus));
|
||||
final message = ref
|
||||
@ -52,8 +56,6 @@ class ResponseDetails extends ConsumerWidget {
|
||||
ref
|
||||
.read(collectionStateNotifierProvider.notifier)
|
||||
.clearResponse(selectedRequest?.id);
|
||||
sm.hideCurrentSnackBar();
|
||||
sm.showSnackBar(getSnackBar('Response cleared'));
|
||||
},
|
||||
),
|
||||
const Expanded(
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:apidash/providers/collection_providers.dart';
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'details_card/details_card.dart';
|
||||
import 'url_card.dart';
|
||||
|
@ -1,10 +1,10 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:file_selector/file_selector.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:mime_dart/mime_dart.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
|
||||
const uuid = Uuid();
|
||||
|
||||
@ -57,7 +57,7 @@ String getTempFileName() {
|
||||
return getNewUuid();
|
||||
}
|
||||
|
||||
Future<FilePickerResult?> pickFile() async {
|
||||
FilePickerResult? pickedResult = await FilePicker.platform.pickFiles();
|
||||
Future<XFile?> pickFile() async {
|
||||
XFile? pickedResult = await openFile();
|
||||
return pickedResult;
|
||||
}
|
||||
|
@ -246,15 +246,12 @@ class ClearResponseButton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Tooltip(
|
||||
message: 'Clear response',
|
||||
child: TextButton(
|
||||
style: TextButton.styleFrom(minimumSize: const Size(40, 40)),
|
||||
return IconButton(
|
||||
tooltip: kTooltipClearResponse,
|
||||
onPressed: onPressed,
|
||||
child: const Icon(
|
||||
icon: const Icon(
|
||||
Icons.delete,
|
||||
size: 20,
|
||||
),
|
||||
size: 16,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1,83 +0,0 @@
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dropdowns.dart';
|
||||
|
||||
class FormDataField extends StatefulWidget {
|
||||
const FormDataField({
|
||||
super.key,
|
||||
required this.keyId,
|
||||
this.initialValue,
|
||||
this.hintText,
|
||||
this.onChanged,
|
||||
this.colorScheme,
|
||||
this.formDataType,
|
||||
this.onFormDataTypeChanged,
|
||||
});
|
||||
|
||||
final String keyId;
|
||||
final String? initialValue;
|
||||
final String? hintText;
|
||||
final void Function(String)? onChanged;
|
||||
final ColorScheme? colorScheme;
|
||||
final FormDataType? formDataType;
|
||||
final void Function(FormDataType?)? onFormDataTypeChanged;
|
||||
|
||||
@override
|
||||
State<FormDataField> createState() => _FormDataFieldState();
|
||||
}
|
||||
|
||||
class _FormDataFieldState extends State<FormDataField> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var colorScheme = widget.colorScheme ?? Theme.of(context).colorScheme;
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: TextFormField(
|
||||
initialValue: widget.initialValue,
|
||||
key: Key(widget.keyId),
|
||||
style: kCodeStyle.copyWith(
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintStyle: kCodeStyle.copyWith(
|
||||
color: colorScheme.outline.withOpacity(
|
||||
kHintOpacity,
|
||||
),
|
||||
),
|
||||
hintText: widget.hintText,
|
||||
contentPadding: const EdgeInsets.only(bottom: 16),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: colorScheme.primary.withOpacity(
|
||||
kHintOpacity,
|
||||
),
|
||||
),
|
||||
),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: colorScheme.surfaceVariant,
|
||||
),
|
||||
),
|
||||
suffixIcon: DropdownButtonFormData(
|
||||
formDataType: widget.formDataType,
|
||||
onChanged: (p0) {
|
||||
if (widget.onFormDataTypeChanged != null) {
|
||||
widget.onFormDataTypeChanged!(p0);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
onChanged: widget.onChanged,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -76,11 +76,14 @@ class _HeaderFieldState extends State<HeaderField> {
|
||||
onChanged: widget.onChanged,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
style: kCodeStyle.copyWith(color: colorScheme.onSurface),
|
||||
style: kCodeStyle.copyWith(
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintStyle: kCodeStyle.copyWith(
|
||||
color: colorScheme.outline.withOpacity(kHintOpacity)),
|
||||
hintText: widget.hintText,
|
||||
contentPadding: const EdgeInsets.only(bottom: 12),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: colorScheme.primary.withOpacity(
|
||||
|
@ -8,6 +8,7 @@ import 'error_message.dart';
|
||||
import 'uint8_audio_player.dart';
|
||||
import 'json_previewer.dart';
|
||||
import 'csv_previewer.dart';
|
||||
import 'video_previewer.dart';
|
||||
import '../consts.dart';
|
||||
|
||||
class Previewer extends StatefulWidget {
|
||||
@ -86,7 +87,12 @@ class _PreviewerState extends State<Previewer> {
|
||||
return CsvPreviewer(body: widget.body);
|
||||
}
|
||||
if (widget.type == kTypeVideo) {
|
||||
// TODO: Video Player
|
||||
try {
|
||||
var preview = VideoPreviewer(videoBytes: widget.bytes);
|
||||
return preview;
|
||||
} catch (e) {
|
||||
return const ErrorMessage(message: kVideoError);
|
||||
}
|
||||
}
|
||||
String message = widget.hasRaw
|
||||
? "$kMimeTypeRawRaiseIssueStart${widget.type}/${widget.subtype}$kMimeTypeRaiseIssue"
|
||||
|
@ -48,16 +48,12 @@ class _RequestPaneState extends State<RequestPane>
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: kPh20v10,
|
||||
padding: kP8,
|
||||
child: SizedBox(
|
||||
height: kHeaderHeight,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
"Request",
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
FilledButton.tonalIcon(
|
||||
onPressed: widget.onPressedCodeButton,
|
||||
icon: Icon(
|
||||
@ -68,7 +64,8 @@ class _RequestPaneState extends State<RequestPane>
|
||||
label: SizedBox(
|
||||
width: 75,
|
||||
child: Text(
|
||||
widget.codePaneVisible ? "Hide Code" : "View Code"),
|
||||
widget.codePaneVisible ? kLabelHideCode : kLabelViewCode,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -79,22 +76,24 @@ class _RequestPaneState extends State<RequestPane>
|
||||
key: Key(widget.selectedId!),
|
||||
controller: _controller,
|
||||
overlayColor: kColorTransparentState,
|
||||
labelPadding: kPh2,
|
||||
onTap: widget.onTapTabBar,
|
||||
tabs: [
|
||||
TabLabel(
|
||||
text: 'URL Params',
|
||||
text: kLabelURLParams,
|
||||
showIndicator: widget.showIndicators[0],
|
||||
),
|
||||
TabLabel(
|
||||
text: 'Headers',
|
||||
text: kLabelHeaders,
|
||||
showIndicator: widget.showIndicators[1],
|
||||
),
|
||||
TabLabel(
|
||||
text: 'Body',
|
||||
text: kLabelBody,
|
||||
showIndicator: widget.showIndicators[2],
|
||||
),
|
||||
],
|
||||
),
|
||||
kVSpacer5,
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
controller: _controller,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
@ -23,7 +24,7 @@ class NotSentWidget extends StatelessWidget {
|
||||
color: color,
|
||||
),
|
||||
Text(
|
||||
'Not Sent',
|
||||
kLabelNotSent,
|
||||
style:
|
||||
Theme.of(context).textTheme.titleMedium?.copyWith(color: color),
|
||||
),
|
||||
@ -33,18 +34,80 @@ class NotSentWidget extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class SendingWidget extends StatelessWidget {
|
||||
const SendingWidget({super.key});
|
||||
class SendingWidget extends StatefulWidget {
|
||||
final DateTime? startSendingTime;
|
||||
const SendingWidget({
|
||||
super.key,
|
||||
required this.startSendingTime,
|
||||
});
|
||||
|
||||
@override
|
||||
State<SendingWidget> createState() => _SendingWidgetState();
|
||||
}
|
||||
|
||||
class _SendingWidgetState extends State<SendingWidget> {
|
||||
int _millisecondsElapsed = 0;
|
||||
Timer? _timer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.startSendingTime != null) {
|
||||
_millisecondsElapsed =
|
||||
(DateTime.now().difference(widget.startSendingTime!).inMilliseconds ~/
|
||||
100) *
|
||||
100;
|
||||
_timer = Timer.periodic(const Duration(milliseconds: 100), _updateTimer);
|
||||
}
|
||||
}
|
||||
|
||||
void _updateTimer(Timer timer) {
|
||||
setState(() {
|
||||
_millisecondsElapsed += 100;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (_timer != null && _timer!.isActive) _timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
return Stack(
|
||||
children: [
|
||||
Center(
|
||||
child: Lottie.asset(kAssetSendingLottie),
|
||||
),
|
||||
Padding(
|
||||
padding: kPh20t40,
|
||||
child: Visibility(
|
||||
visible: _millisecondsElapsed >= 0,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Lottie.asset(kAssetSendingLottie),
|
||||
Icon(
|
||||
Icons.alarm,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(
|
||||
'Time elapsed: ${humanizeDuration(Duration(milliseconds: _millisecondsElapsed))}',
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: false,
|
||||
style: kTextStyleButton.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -66,42 +129,19 @@ class ResponsePaneHeader extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: kPh20v10,
|
||||
padding: kPv8,
|
||||
child: SizedBox(
|
||||
height: kHeaderHeight,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
const TextSpan(
|
||||
text: "Response (",
|
||||
),
|
||||
TextSpan(
|
||||
text: "$responseStatus",
|
||||
style: TextStyle(
|
||||
color: getResponseStatusCodeColor(
|
||||
responseStatus,
|
||||
brightness: Theme.of(context).brightness,
|
||||
),
|
||||
fontFamily: kCodeStyle.fontFamily,
|
||||
),
|
||||
),
|
||||
const TextSpan(
|
||||
text: ")",
|
||||
),
|
||||
],
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
kHSpacer20,
|
||||
kHSpacer10,
|
||||
Expanded(
|
||||
child: Text(
|
||||
message ?? "",
|
||||
"$responseStatus: ${message ?? '-'}",
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
fontFamily: kCodeStyle.fontFamily,
|
||||
color: getResponseStatusCodeColor(
|
||||
responseStatus,
|
||||
@ -110,10 +150,10 @@ class ResponsePaneHeader extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
kHSpacer20,
|
||||
kHSpacer10,
|
||||
Text(
|
||||
humanizeDuration(time),
|
||||
style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
fontFamily: kCodeStyle.fontFamily,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
@ -163,31 +203,15 @@ class _ResponseTabViewState extends State<ResponseTabView>
|
||||
TabBar(
|
||||
key: Key(widget.selectedId!),
|
||||
controller: _controller,
|
||||
labelPadding: kPh2,
|
||||
overlayColor: kColorTransparentState,
|
||||
onTap: (index) {},
|
||||
tabs: const [
|
||||
SizedBox(
|
||||
height: kTabHeight,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Body',
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: false,
|
||||
style: kTextStyleButton,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: kTabHeight,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Headers',
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.fade,
|
||||
style: kTextStyleButton,
|
||||
),
|
||||
TabLabel(
|
||||
text: kLabelResponseBody,
|
||||
),
|
||||
TabLabel(
|
||||
text: kLabelHeaders,
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -227,8 +251,8 @@ class ResponseHeadersHeader extends StatelessWidget {
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"$name (${map.length} items)",
|
||||
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||
"$name (${map.length} $kLabelItems)",
|
||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@ -243,8 +267,6 @@ class ResponseHeadersHeader extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
const kHeaderRow = ["Header Name", "Header Value"];
|
||||
|
||||
class ResponseHeaders extends StatelessWidget {
|
||||
const ResponseHeaders({
|
||||
super.key,
|
||||
@ -263,7 +285,7 @@ class ResponseHeaders extends StatelessWidget {
|
||||
children: [
|
||||
ResponseHeadersHeader(
|
||||
map: responseHeaders,
|
||||
name: "Response Headers",
|
||||
name: kLabelResponseHeaders,
|
||||
),
|
||||
if (responseHeaders.isNotEmpty) kVSpacer5,
|
||||
if (responseHeaders.isNotEmpty)
|
||||
@ -275,7 +297,7 @@ class ResponseHeaders extends StatelessWidget {
|
||||
kVSpacer10,
|
||||
ResponseHeadersHeader(
|
||||
map: requestHeaders,
|
||||
name: "Request Headers",
|
||||
name: kLabelRequestHeaders,
|
||||
),
|
||||
if (requestHeaders.isNotEmpty) kVSpacer5,
|
||||
if (requestHeaders.isNotEmpty)
|
||||
@ -302,20 +324,18 @@ class ResponseBody extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final responseModel = selectedRequestModel?.responseModel;
|
||||
if (responseModel == null) {
|
||||
return const ErrorMessage(
|
||||
message:
|
||||
'Error: Response data does not exist. $kUnexpectedRaiseIssue');
|
||||
return const ErrorMessage(message: '$kMsgError $kUnexpectedRaiseIssue');
|
||||
}
|
||||
|
||||
var body = responseModel.body;
|
||||
var formattedBody = responseModel.formattedBody;
|
||||
if (body == null) {
|
||||
return const ErrorMessage(
|
||||
message: 'Response body is missing (null). $kUnexpectedRaiseIssue');
|
||||
message: '$kMsgNullBody $kUnexpectedRaiseIssue');
|
||||
}
|
||||
if (body.isEmpty) {
|
||||
return const ErrorMessage(
|
||||
message: 'No content',
|
||||
message: kMsgNoContent,
|
||||
showIcon: false,
|
||||
showIssueButton: false,
|
||||
);
|
||||
@ -325,7 +345,7 @@ class ResponseBody extends StatelessWidget {
|
||||
if (mediaType == null) {
|
||||
return ErrorMessage(
|
||||
message:
|
||||
'Unknown Response Content-Type - ${responseModel.contentType}. $kUnexpectedRaiseIssue');
|
||||
'$kMsgUnknowContentType - ${responseModel.contentType}. $kUnexpectedRaiseIssue');
|
||||
}
|
||||
|
||||
var responseBodyView = getResponseBodyViewOptions(mediaType);
|
||||
|
@ -2,7 +2,11 @@ import 'package:flutter/material.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
|
||||
class TabLabel extends StatelessWidget {
|
||||
const TabLabel({super.key, required this.text, this.showIndicator = false});
|
||||
const TabLabel({
|
||||
super.key,
|
||||
required this.text,
|
||||
this.showIndicator = false,
|
||||
});
|
||||
final String text;
|
||||
final bool showIndicator;
|
||||
|
||||
@ -18,14 +22,14 @@ class TabLabel extends StatelessWidget {
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: false,
|
||||
style: kTextStyleButton,
|
||||
style: kTextStyleTab,
|
||||
),
|
||||
),
|
||||
if (showIndicator)
|
||||
const Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
padding: EdgeInsets.only(top: 1),
|
||||
child: Icon(
|
||||
Icons.circle,
|
||||
size: 6,
|
||||
|
@ -68,6 +68,7 @@ class CellField extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
hintText: hintText,
|
||||
contentPadding: const EdgeInsets.only(bottom: 12),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: clrScheme.primary.withOpacity(
|
||||
@ -94,14 +95,39 @@ class JsonSearchField extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextField(
|
||||
return RawTextField(
|
||||
controller: controller,
|
||||
onChanged: onChanged,
|
||||
style: kCodeStyle,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Search..',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RawTextField extends StatelessWidget {
|
||||
const RawTextField({
|
||||
super.key,
|
||||
this.onChanged,
|
||||
this.controller,
|
||||
this.hintText,
|
||||
this.style,
|
||||
});
|
||||
|
||||
final void Function(String)? onChanged;
|
||||
final TextEditingController? controller;
|
||||
final String? hintText;
|
||||
final TextStyle? style;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextField(
|
||||
controller: controller,
|
||||
onChanged: onChanged,
|
||||
style: style,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: InputBorder.none,
|
||||
hintText: 'Search..',
|
||||
hintText: hintText,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
147
lib/widgets/video_previewer.dart
Normal file
147
lib/widgets/video_previewer.dart
Normal file
@ -0,0 +1,147 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:fvp/fvp.dart' as fvp;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class VideoPreviewer extends StatefulWidget {
|
||||
const VideoPreviewer({
|
||||
super.key,
|
||||
required this.videoBytes,
|
||||
});
|
||||
|
||||
final Uint8List videoBytes;
|
||||
|
||||
@override
|
||||
State<VideoPreviewer> createState() => _VideoPreviewerState();
|
||||
}
|
||||
|
||||
class _VideoPreviewerState extends State<VideoPreviewer> {
|
||||
VideoPlayerController? _videoController;
|
||||
bool _isPlaying = false;
|
||||
File? _tempVideoFile;
|
||||
bool _showControls = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
registerWithAllPlatforms();
|
||||
_initializeVideoPlayer();
|
||||
}
|
||||
|
||||
void registerWithAllPlatforms() {
|
||||
try {
|
||||
fvp.registerWith();
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
|
||||
void _initializeVideoPlayer() async {
|
||||
final tempDir = await getTemporaryDirectory();
|
||||
_tempVideoFile = File(
|
||||
'${tempDir.path}/temp_video_${DateTime.now().millisecondsSinceEpoch}');
|
||||
try {
|
||||
await _tempVideoFile?.writeAsBytes(widget.videoBytes);
|
||||
_videoController = VideoPlayerController.file(_tempVideoFile!)
|
||||
..initialize().then((_) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_videoController!.play();
|
||||
_videoController!.setLooping(true);
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final iconColor = Theme.of(context).iconTheme.color;
|
||||
final progressBarColors = VideoProgressColors(
|
||||
playedColor: iconColor!,
|
||||
bufferedColor: iconColor.withOpacity(0.5),
|
||||
backgroundColor: iconColor.withOpacity(0.3),
|
||||
);
|
||||
return Scaffold(
|
||||
body: MouseRegion(
|
||||
onEnter: (_) => setState(() => _showControls = true),
|
||||
onExit: (_) => setState(() => _showControls = false),
|
||||
child: Stack(
|
||||
children: [
|
||||
Center(
|
||||
child: _videoController?.value.isInitialized == true
|
||||
? AspectRatio(
|
||||
aspectRatio: _videoController!.value.aspectRatio,
|
||||
child: VideoPlayer(_videoController!),
|
||||
)
|
||||
: const CircularProgressIndicator(),
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: _videoController?.value.isInitialized == true
|
||||
? SizedBox(
|
||||
height: 50.0,
|
||||
child: VideoProgressIndicator(
|
||||
_videoController!,
|
||||
allowScrubbing: true,
|
||||
padding: const EdgeInsets.all(20),
|
||||
colors: progressBarColors,
|
||||
),
|
||||
)
|
||||
: Container(height: 0),
|
||||
),
|
||||
if (_showControls)
|
||||
Center(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (_videoController!.value.isPlaying) {
|
||||
_videoController!.pause();
|
||||
} else {
|
||||
_videoController!.play();
|
||||
}
|
||||
setState(() {
|
||||
_isPlaying = !_isPlaying;
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Icon(
|
||||
_isPlaying ? Icons.play_arrow : Icons.pause,
|
||||
size: 64,
|
||||
color: iconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_videoController?.pause();
|
||||
_videoController?.dispose();
|
||||
if (!kIsRunningTests) {
|
||||
Future.delayed(const Duration(seconds: 1), () async {
|
||||
try {
|
||||
if (_tempVideoFile != null) {
|
||||
await _tempVideoFile!.delete();
|
||||
}
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@ export 'dropdowns.dart';
|
||||
export 'editor_json.dart';
|
||||
export 'editor.dart';
|
||||
export 'error_message.dart';
|
||||
export 'form_data_field.dart';
|
||||
export 'headerfield.dart';
|
||||
export 'intro_message.dart';
|
||||
export 'json_previewer.dart';
|
||||
|
160
pubspec.lock
160
pubspec.lock
@ -49,14 +49,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.18"
|
||||
axis_layout:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: axis_layout
|
||||
sha256: "9ba44f279f39121065d811e72da892de86f5613d68eb0b295f60d021ea8f2a59"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
barcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -209,6 +201,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.7.2"
|
||||
cross_file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cross_file
|
||||
sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.4+1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -217,6 +217,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
csslib:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: csslib
|
||||
sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
csv:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -233,14 +241,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.6"
|
||||
davi:
|
||||
data_table_2:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: davi
|
||||
sha256: "4105870281c4c33e8e017e21e212b96fd2637b4c1a35b2a56f14aaa4acdf6f0d"
|
||||
name: data_table_2
|
||||
sha256: fdb0551f103f1daf837bddfde14619fd9e683408833a618c9afabeb533fce88c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
version: "2.5.11"
|
||||
eventify:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -289,14 +297,70 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
file_picker:
|
||||
file_selector:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: file_picker
|
||||
sha256: caa6bc229eab3e32eb2f37b53a5f9d22a6981474afd210c512a7546c1e1a04f6
|
||||
name: file_selector
|
||||
sha256: "5019692b593455127794d5718304ff1ae15447dea286cdda9f0db2a796a1b828"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
version: "1.0.3"
|
||||
file_selector_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_android
|
||||
sha256: "1cd66575f063b689e041aec836905ba7be18d76c9f0634d0d75daec825f67095"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.0+7"
|
||||
file_selector_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_ios
|
||||
sha256: b015154e6d9fddbc4d08916794df170b44531798c8dd709a026df162d07ad81d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1+8"
|
||||
file_selector_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_linux
|
||||
sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.2+1"
|
||||
file_selector_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_macos
|
||||
sha256: b15c3da8bd4908b9918111fa486903f5808e388b8d1c559949f584725a6594d6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.3+3"
|
||||
file_selector_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_platform_interface
|
||||
sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.2"
|
||||
file_selector_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_web
|
||||
sha256: "619e431b224711a3869e30dbd7d516f5f5a4f04b265013a50912f39e1abc88c8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.4+1"
|
||||
file_selector_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_windows
|
||||
sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.3+1"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -382,14 +446,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.21"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.17"
|
||||
flutter_riverpod:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -448,6 +504,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
fvp:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: fvp
|
||||
sha256: "995328479ba4641da6760ddc84a168db157a3b9db4f0417fa68713d99344a146"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.14.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -496,6 +560,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: html
|
||||
sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.15.4"
|
||||
html_unescape:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1294,6 +1366,46 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
video_player:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: video_player
|
||||
sha256: afc65f4b8bcb2c188f64a591f84fb471f4f2e19fc607c65fd8d2f8fedb3dec23
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.8.3"
|
||||
video_player_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_android
|
||||
sha256: "4dd9b8b86d70d65eecf3dcabfcdfbb9c9115d244d022654aba49a00336d540c2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.12"
|
||||
video_player_avfoundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_avfoundation
|
||||
sha256: "309e3962795e761be010869bae65c0b0e45b5230c5cee1bec72197ca7db040ed"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.6"
|
||||
video_player_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: video_player_platform_interface
|
||||
sha256: "236454725fafcacf98f0f39af0d7c7ab2ce84762e3b63f2cbb3ef9a7e0550bc6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.2"
|
||||
video_player_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_web
|
||||
sha256: "41245cef5ef29c4585dbabcbcbe9b209e34376642c7576cabf11b4ad9289d6e4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -15,7 +15,6 @@ dependencies:
|
||||
flutter_riverpod: ^2.5.1
|
||||
riverpod: ^2.5.1
|
||||
uuid: ^4.3.3
|
||||
davi: ^3.4.1
|
||||
http: ^1.2.1
|
||||
http_parser: ^4.0.2
|
||||
collection: ^1.17.2
|
||||
@ -44,18 +43,22 @@ dependencies:
|
||||
package_info_plus: ^5.0.1
|
||||
flutter_typeahead: ^5.2.0
|
||||
provider: ^6.1.2
|
||||
fvp: ^0.14.0
|
||||
video_player: ^2.3.2
|
||||
video_player_platform_interface: ^6.2.2
|
||||
json_data_explorer:
|
||||
git:
|
||||
url: https://github.com/foss42/json_data_explorer.git
|
||||
ref: b7dde2f85dff4f482eed7eda4ef2a71344ef8b3a
|
||||
scrollable_positioned_list: ^0.3.8
|
||||
file_picker: ^6.2.0
|
||||
flutter_svg: ^2.0.10+1
|
||||
vector_graphics_compiler: ^1.1.9+1
|
||||
code_builder: ^4.10.0
|
||||
dart_style: ^2.3.6
|
||||
json_text_field: ^1.1.0
|
||||
csv: ^6.0.0
|
||||
data_table_2: ^2.5.11
|
||||
file_selector: ^1.0.3
|
||||
|
||||
dependency_overrides:
|
||||
web: ^0.5.0
|
||||
|
982
test/codegen/csharp_rest_sharp_codgen_test.dart
Normal file
982
test/codegen/csharp_rest_sharp_codgen_test.dart
Normal file
@ -0,0 +1,982 @@
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:apidash/screens/home_page/editor_pane/details_card/code_pane.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../request_models.dart';
|
||||
|
||||
void main() {
|
||||
group("Get Request Test", () {
|
||||
test("Get 1", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("", Method.Get);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet1, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Get 2", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/country/data", Method.Get);
|
||||
|
||||
request.AddQueryParameter("code", "US");
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet2, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Get 3", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/country/data", Method.Get);
|
||||
|
||||
request.AddQueryParameter("code", "IND");
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet3, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Get 4", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/humanize/social", Method.Get);
|
||||
|
||||
request.AddQueryParameter("num", "8700000");
|
||||
request.AddQueryParameter("digits", "3");
|
||||
request.AddQueryParameter("system", "SS");
|
||||
request.AddQueryParameter("add_space", "true");
|
||||
request.AddQueryParameter("trailing_zeros", "true");
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet4, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Get 5", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.github.com";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/repos/foss42/apidash", Method.Get);
|
||||
|
||||
request.AddHeader("User-Agent", "Test Agent");
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet5, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Get 6", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.github.com";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/repos/foss42/apidash", Method.Get);
|
||||
|
||||
request.AddQueryParameter("raw", "true");
|
||||
|
||||
request.AddHeader("User-Agent", "Test Agent");
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet6, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Get 7", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("", Method.Get);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet7, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Get 8", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.github.com";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/repos/foss42/apidash", Method.Get);
|
||||
|
||||
request.AddQueryParameter("raw", "true");
|
||||
|
||||
request.AddHeader("User-Agent", "Test Agent");
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet8, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Get 9", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/humanize/social", Method.Get);
|
||||
|
||||
request.AddQueryParameter("num", "8700000");
|
||||
request.AddQueryParameter("add_space", "true");
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet9, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Get 10", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/humanize/social", Method.Get);
|
||||
|
||||
request.AddHeader("User-Agent", "Test Agent");
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet10, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Get 11", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/humanize/social", Method.Get);
|
||||
|
||||
request.AddQueryParameter("num", "8700000");
|
||||
request.AddQueryParameter("digits", "3");
|
||||
|
||||
request.AddHeader("User-Agent", "Test Agent");
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet11, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Get 12", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/humanize/social", Method.Get);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelGet12, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
|
||||
group("Head Request Test", () {
|
||||
test("Head 1", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("", Method.Head);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelHead1, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test("Head 2", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "http://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("", Method.Head);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelHead2, "http"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
|
||||
group("Post Request Test", () {
|
||||
test("Post 1", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/case/lower", Method.Post);
|
||||
|
||||
request.AddHeader("Content-Type", "text/plain");
|
||||
|
||||
var textBody = "{\n\"text\": \"I LOVE Flutter\"\n}";
|
||||
request.AddStringBody(textBody, ContentType.Plain);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelPost1, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test("Post 2", () {
|
||||
const expectedCode = """
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/case/lower", Method.Post);
|
||||
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
|
||||
var jsonBody = new {
|
||||
text = "I LOVE Flutter",
|
||||
flag = "null",
|
||||
male = "true",
|
||||
female = "false",
|
||||
no = "1.2",
|
||||
arr = "[null, true, false, null]"
|
||||
};
|
||||
request.AddJsonBody(jsonBody);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelPost2, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test("Post 3", () {
|
||||
const expectedCode = """
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/case/lower", Method.Post);
|
||||
|
||||
request.AddHeader("User-Agent", "Test Agent");
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
|
||||
var jsonBody = new {
|
||||
text = "I LOVE Flutter"
|
||||
};
|
||||
request.AddJsonBody(jsonBody);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelPost3, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test("Post 4", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/io/form", Method.Post);
|
||||
|
||||
request.AlwaysMultipartFormData = true;
|
||||
request.AddParameter("text", "API", ParameterType.GetOrPost);
|
||||
request.AddParameter("sep", "|", ParameterType.GetOrPost);
|
||||
request.AddParameter("times", "3", ParameterType.GetOrPost);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelPost4, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test("Post 5", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/io/form", Method.Post);
|
||||
|
||||
request.AddHeader("User-Agent", "Test Agent");
|
||||
|
||||
request.AlwaysMultipartFormData = true;
|
||||
request.AddParameter("text", "API", ParameterType.GetOrPost);
|
||||
request.AddParameter("sep", "|", ParameterType.GetOrPost);
|
||||
request.AddParameter("times", "3", ParameterType.GetOrPost);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelPost5, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test("Post 6", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/io/img", Method.Post);
|
||||
|
||||
request.AlwaysMultipartFormData = true;
|
||||
var options = new FileParameterOptions
|
||||
{
|
||||
DisableFilenameEncoding = true
|
||||
};
|
||||
request.AddParameter("token", "xyz", ParameterType.GetOrPost);
|
||||
request.AddFile("imfile", "/Documents/up/1.png", options: options);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelPost6, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test("Post 7", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/io/img", Method.Post);
|
||||
|
||||
request.AlwaysMultipartFormData = true;
|
||||
var options = new FileParameterOptions
|
||||
{
|
||||
DisableFilenameEncoding = true
|
||||
};
|
||||
request.AddParameter("token", "xyz", ParameterType.GetOrPost);
|
||||
request.AddFile("imfile", "/Documents/up/1.png", options: options);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelPost7, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test("Post 8", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/io/form", Method.Post);
|
||||
|
||||
request.AddQueryParameter("size", "2");
|
||||
request.AddQueryParameter("len", "3");
|
||||
|
||||
request.AlwaysMultipartFormData = true;
|
||||
request.AddParameter("text", "API", ParameterType.GetOrPost);
|
||||
request.AddParameter("sep", "|", ParameterType.GetOrPost);
|
||||
request.AddParameter("times", "3", ParameterType.GetOrPost);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelPost8, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test("Post 9", () {
|
||||
const expectedCode = r"""
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://api.apidash.dev";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/io/img", Method.Post);
|
||||
|
||||
request.AddQueryParameter("size", "2");
|
||||
request.AddQueryParameter("len", "3");
|
||||
|
||||
request.AddHeader("User-Agent", "Test Agent");
|
||||
request.AddHeader("Keep-Alive", "true");
|
||||
|
||||
request.AlwaysMultipartFormData = true;
|
||||
var options = new FileParameterOptions
|
||||
{
|
||||
DisableFilenameEncoding = true
|
||||
};
|
||||
request.AddParameter("token", "xyz", ParameterType.GetOrPost);
|
||||
request.AddFile("imfile", "/Documents/up/1.png", options: options);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelPost9, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
|
||||
group("Put Request Test", () {
|
||||
test("Put 1", () {
|
||||
const expectedCode = """
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://reqres.in";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/api/users/2", Method.Put);
|
||||
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
|
||||
var jsonBody = new {
|
||||
name = "morpheus",
|
||||
job = "zion resident"
|
||||
};
|
||||
request.AddJsonBody(jsonBody);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelPut1, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
|
||||
group("Patch Request Test", () {
|
||||
test("Patch 1", () {
|
||||
const expectedCode = """
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://reqres.in";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/api/users/2", Method.Patch);
|
||||
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
|
||||
var jsonBody = new {
|
||||
name = "marfeus",
|
||||
job = "accountant"
|
||||
};
|
||||
request.AddJsonBody(jsonBody);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelPatch1, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
|
||||
group("Delete Request Test", () {
|
||||
test("Delete 1", () {
|
||||
const expectedCode = """
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://reqres.in";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/api/users/2", Method.Delete);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelDelete1, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test("Delete 2", () {
|
||||
const expectedCode = """
|
||||
using System;
|
||||
using RestSharp;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class Program
|
||||
{
|
||||
static async Task Main(){
|
||||
try{
|
||||
const String _baseUrl = "https://reqres.in";
|
||||
var client = new RestClient(_baseUrl);
|
||||
|
||||
var request = new RestRequest("/api/users/2", Method.Delete);
|
||||
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
|
||||
var jsonBody = new {
|
||||
name = "marfeus",
|
||||
job = "accountant"
|
||||
};
|
||||
request.AddJsonBody(jsonBody);
|
||||
|
||||
var response = await client.ExecuteAsync(request);
|
||||
Console.WriteLine("Status Code: " + (int)response.StatusCode);
|
||||
Console.WriteLine("Response Content: " + response.Content);
|
||||
}
|
||||
catch(Exception ex){
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
expect(
|
||||
codegen.getCode(
|
||||
CodegenLanguage.cSharpRestSharp, requestModelDelete2, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
}
|
1109
test/codegen/java_httpclient_codegen_test.dart
Normal file
1109
test/codegen/java_httpclient_codegen_test.dart
Normal file
File diff suppressed because it is too large
Load Diff
@ -8,76 +8,72 @@ void main() {
|
||||
|
||||
group('GET Request', () {
|
||||
test('GET 1', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev"
|
||||
|
||||
response = HTTP.request("GET", url, status_exception=false)
|
||||
|
||||
response = HTTP.get(url)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet1, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test('GET 2', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/country/data"
|
||||
|
||||
|
||||
params = Dict(
|
||||
"code"=> "US"
|
||||
"code" => "US",
|
||||
)
|
||||
|
||||
response = HTTP.get(url, query=params)
|
||||
response = HTTP.request("GET", url, query=params, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet2, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test('GET 3', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/country/data"
|
||||
|
||||
|
||||
params = Dict(
|
||||
"code"=> "IND"
|
||||
"code" => "IND",
|
||||
)
|
||||
|
||||
response = HTTP.get(url, query=params)
|
||||
response = HTTP.request("GET", url, query=params, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet3, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test('GET 4', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/humanize/social"
|
||||
|
||||
|
||||
params = Dict(
|
||||
"num" => "8700000",
|
||||
"digits" => "3",
|
||||
"system" => "SS",
|
||||
"add_space" => "true",
|
||||
"trailing_zeros"=> "true"
|
||||
"trailing_zeros" => "true",
|
||||
)
|
||||
|
||||
response = HTTP.get(url, query=params)
|
||||
response = HTTP.request("GET", url, query=params, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet4, "https"),
|
||||
@ -85,19 +81,18 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
|
||||
test('GET 5', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.github.com/repos/foss42/apidash"
|
||||
|
||||
|
||||
headers = Dict(
|
||||
"User-Agent"=> "Test Agent"
|
||||
"User-Agent" => "Test Agent",
|
||||
)
|
||||
|
||||
response = HTTP.get(url, headers=headers)
|
||||
response = HTTP.request("GET", url, headers=headers, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet5, "https"),
|
||||
@ -105,23 +100,22 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
|
||||
test('GET 6', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.github.com/repos/foss42/apidash"
|
||||
|
||||
|
||||
params = Dict(
|
||||
"raw"=> "true"
|
||||
"raw" => "true",
|
||||
)
|
||||
|
||||
headers = Dict(
|
||||
"User-Agent"=> "Test Agent"
|
||||
"User-Agent" => "Test Agent",
|
||||
)
|
||||
|
||||
response = HTTP.get(url, query=params, headers=headers)
|
||||
response = HTTP.request("GET", url, headers=headers, query=params, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet6, "https"),
|
||||
@ -129,15 +123,14 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
|
||||
test('GET 7', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev"
|
||||
|
||||
response = HTTP.request("GET", url, status_exception=false)
|
||||
|
||||
response = HTTP.get(url)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet7, "https"),
|
||||
@ -145,23 +138,22 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
|
||||
test('GET 8', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.github.com/repos/foss42/apidash"
|
||||
|
||||
|
||||
params = Dict(
|
||||
"raw"=> "true"
|
||||
"raw" => "true",
|
||||
)
|
||||
|
||||
headers = Dict(
|
||||
"User-Agent"=> "Test Agent"
|
||||
"User-Agent" => "Test Agent",
|
||||
)
|
||||
|
||||
response = HTTP.get(url, query=params, headers=headers)
|
||||
response = HTTP.request("GET", url, headers=headers, query=params, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet8, "https"),
|
||||
@ -169,20 +161,19 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
|
||||
test('GET 9', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/humanize/social"
|
||||
|
||||
|
||||
params = Dict(
|
||||
"num" => "8700000",
|
||||
"add_space"=> "true"
|
||||
"add_space" => "true",
|
||||
)
|
||||
|
||||
response = HTTP.get(url, query=params)
|
||||
response = HTTP.request("GET", url, query=params, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.juliaHttp, requestModelGet9, "https"),
|
||||
@ -190,19 +181,18 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
|
||||
test('GET 10', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/humanize/social"
|
||||
|
||||
|
||||
headers = Dict(
|
||||
"User-Agent"=> "Test Agent"
|
||||
"User-Agent" => "Test Agent",
|
||||
)
|
||||
|
||||
response = HTTP.get(url, headers=headers)
|
||||
response = HTTP.request("GET", url, headers=headers, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
@ -211,24 +201,23 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
|
||||
test('GET 11', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/humanize/social"
|
||||
|
||||
|
||||
params = Dict(
|
||||
"num" => "8700000",
|
||||
"digits"=> "3"
|
||||
"digits" => "3",
|
||||
)
|
||||
|
||||
headers = Dict(
|
||||
"User-Agent"=> "Test Agent"
|
||||
"User-Agent" => "Test Agent",
|
||||
)
|
||||
|
||||
response = HTTP.get(url, query=params, headers=headers)
|
||||
response = HTTP.request("GET", url, headers=headers, query=params, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
@ -237,15 +226,14 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
|
||||
test('GET 12', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/humanize/social"
|
||||
|
||||
response = HTTP.request("GET", url, status_exception=false)
|
||||
|
||||
response = HTTP.get(url)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
@ -256,15 +244,14 @@ println("Response Body:", String(response.body))
|
||||
|
||||
group('HEAD Request', () {
|
||||
test('HEAD 1', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev"
|
||||
|
||||
response = HTTP.request("HEAD", url, status_exception=false)
|
||||
|
||||
response = HTTP.head(url)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
@ -273,43 +260,40 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
|
||||
test('HEAD 2', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev"
|
||||
url = "http://api.apidash.dev"
|
||||
|
||||
response = HTTP.request("HEAD", url, status_exception=false)
|
||||
|
||||
response = HTTP.head(url)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelHead2, "https"),
|
||||
codeGen.getCode(CodegenLanguage.juliaHttp, requestModelHead2, "http"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
|
||||
group('POST Request', () {
|
||||
test('POST 1', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r'''using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/case/lower"
|
||||
|
||||
|
||||
payload = Dict(
|
||||
"text"=> "I LOVE Flutter"
|
||||
)
|
||||
payload = """{
|
||||
"text": "I LOVE Flutter"
|
||||
}"""
|
||||
|
||||
headers = Dict(
|
||||
"content-type"=> "text/plain"
|
||||
"content-type" => "text/plain",
|
||||
)
|
||||
|
||||
response = HTTP.post(url, payload=payload, headers=headers)
|
||||
response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
""";
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
''';
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelPost1, "https"),
|
||||
@ -317,72 +301,234 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
|
||||
test('POST 2', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r'''using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/case/lower"
|
||||
|
||||
payload = """{
|
||||
"text": "I LOVE Flutter",
|
||||
"flag": null,
|
||||
"male": true,
|
||||
"female": false,
|
||||
"no": 1.2,
|
||||
"arr": ["null", "true", "false", null]
|
||||
}"""
|
||||
|
||||
payload = Dict(
|
||||
"text"=> "I LOVE Flutter",
|
||||
"flag"=> null,
|
||||
"male"=> true,
|
||||
"female"=> false,
|
||||
"no"=> 1.2,
|
||||
"arr"=> ["null", "true", "false", null]
|
||||
headers = Dict(
|
||||
"content-type" => "application/json",
|
||||
)
|
||||
|
||||
response = HTTP.post(url, JSON.json(payload))
|
||||
response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
""";
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
''';
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelPost2, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test('POST 3', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r'''using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/case/lower"
|
||||
|
||||
|
||||
payload = Dict(
|
||||
"text"=> "I LOVE Flutter"
|
||||
)
|
||||
payload = """{
|
||||
"text": "I LOVE Flutter"
|
||||
}"""
|
||||
|
||||
headers = Dict(
|
||||
"User-Agent"=> "Test Agent"
|
||||
"User-Agent" => "Test Agent",
|
||||
"content-type" => "application/json",
|
||||
)
|
||||
|
||||
response = HTTP.post(url, JSON.json(payload), headers=headers)
|
||||
response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
""";
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
''';
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelPost3, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test('POST 4', () {
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/io/form"
|
||||
|
||||
data = Dict(
|
||||
"text" => "API",
|
||||
"sep" => "|",
|
||||
"times" => "3",
|
||||
)
|
||||
|
||||
payload = HTTP.Form(data)
|
||||
|
||||
response = HTTP.request("POST", url, body=payload, status_exception=false)
|
||||
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelPost4, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test('POST 5', () {
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/io/form"
|
||||
|
||||
data = Dict(
|
||||
"text" => "API",
|
||||
"sep" => "|",
|
||||
"times" => "3",
|
||||
)
|
||||
|
||||
payload = HTTP.Form(data)
|
||||
|
||||
headers = Dict(
|
||||
"User-Agent" => "Test Agent",
|
||||
)
|
||||
|
||||
response = HTTP.request("POST", url, headers=headers, body=payload, status_exception=false)
|
||||
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelPost5, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test('POST 6', () {
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/io/img"
|
||||
|
||||
data = Dict(
|
||||
"token" => "xyz",
|
||||
"imfile" => open("/Documents/up/1.png"),
|
||||
)
|
||||
|
||||
payload = HTTP.Form(data)
|
||||
|
||||
response = HTTP.request("POST", url, body=payload, status_exception=false)
|
||||
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelPost6, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test('POST 7', () {
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/io/img"
|
||||
|
||||
data = Dict(
|
||||
"token" => "xyz",
|
||||
"imfile" => open("/Documents/up/1.png"),
|
||||
)
|
||||
|
||||
payload = HTTP.Form(data)
|
||||
|
||||
response = HTTP.request("POST", url, body=payload, status_exception=false)
|
||||
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelPost7, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test('POST 8', () {
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/io/form"
|
||||
|
||||
params = Dict(
|
||||
"size" => "2",
|
||||
"len" => "3",
|
||||
)
|
||||
|
||||
data = Dict(
|
||||
"text" => "API",
|
||||
"sep" => "|",
|
||||
"times" => "3",
|
||||
)
|
||||
|
||||
payload = HTTP.Form(data)
|
||||
|
||||
response = HTTP.request("POST", url, body=payload, query=params, status_exception=false)
|
||||
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelPost8, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test('POST 9', () {
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://api.apidash.dev/io/img"
|
||||
|
||||
params = Dict(
|
||||
"size" => "2",
|
||||
"len" => "3",
|
||||
)
|
||||
|
||||
data = Dict(
|
||||
"token" => "xyz",
|
||||
"imfile" => open("/Documents/up/1.png"),
|
||||
)
|
||||
|
||||
payload = HTTP.Form(data)
|
||||
|
||||
headers = Dict(
|
||||
"User-Agent" => "Test Agent",
|
||||
"Keep-Alive" => "true",
|
||||
)
|
||||
|
||||
response = HTTP.request("POST", url, headers=headers, body=payload, query=params, status_exception=false)
|
||||
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelPost9, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
group('PUT Request', () {
|
||||
test('PUT 1', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r'''using HTTP
|
||||
|
||||
url = "https://reqres.in/api/users/2"
|
||||
|
||||
payload = """{
|
||||
"name": "morpheus",
|
||||
"job": "zion resident"
|
||||
}"""
|
||||
|
||||
payload = Dict(
|
||||
"name"=> "morpheus",
|
||||
"job"=> "zion resident"
|
||||
headers = Dict(
|
||||
"content-type" => "application/json",
|
||||
)
|
||||
|
||||
response = HTTP.put(url, JSON.json(payload))
|
||||
response = HTTP.request("PUT", url, headers=headers, body=payload, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
""";
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
''';
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.juliaHttp, requestModelPut1, "https"),
|
||||
expectedCode);
|
||||
@ -390,21 +536,24 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
group('PATCH Request', () {
|
||||
test('PATCH 1', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r'''using HTTP
|
||||
|
||||
url = "https://reqres.in/api/users/2"
|
||||
|
||||
payload = """{
|
||||
"name": "marfeus",
|
||||
"job": "accountant"
|
||||
}"""
|
||||
|
||||
payload = Dict(
|
||||
"name"=> "marfeus",
|
||||
"job"=> "accountant"
|
||||
headers = Dict(
|
||||
"content-type" => "application/json",
|
||||
)
|
||||
|
||||
response = HTTP.patch(url, JSON.json(payload))
|
||||
response = HTTP.request("PATCH", url, headers=headers, body=payload, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
""";
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
''';
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelPatch1, "https"),
|
||||
@ -413,15 +562,14 @@ println("Response Body:", String(response.body))
|
||||
});
|
||||
group('DELETE Request', () {
|
||||
test('DELETE 1', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r"""using HTTP
|
||||
|
||||
url = "https://reqres.in/api/users/2"
|
||||
|
||||
response = HTTP.request("DELETE", url, status_exception=false)
|
||||
|
||||
response = HTTP.delete(url)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
@ -429,21 +577,24 @@ println("Response Body:", String(response.body))
|
||||
expectedCode);
|
||||
});
|
||||
test('DELETE 2', () {
|
||||
const expectedCode = r"""using HTTP,JSON
|
||||
const expectedCode = r'''using HTTP
|
||||
|
||||
url = "https://reqres.in/api/users/2"
|
||||
|
||||
payload = """{
|
||||
"name": "marfeus",
|
||||
"job": "accountant"
|
||||
}"""
|
||||
|
||||
payload = Dict(
|
||||
"name"=> "marfeus",
|
||||
"job"=> "accountant"
|
||||
headers = Dict(
|
||||
"content-type" => "application/json",
|
||||
)
|
||||
|
||||
response = HTTP.delete(url, JSON.json(payload))
|
||||
response = HTTP.request("DELETE", url, headers=headers, body=payload, status_exception=false)
|
||||
|
||||
println("Status Code:", response.status)
|
||||
println("Response Body:", String(response.body))
|
||||
""";
|
||||
println("Status Code: $(response.status) $(HTTP.StatusCodes.statustext(response.status))")
|
||||
println("Response Body: \n$(String(response.body))")
|
||||
''';
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.juliaHttp, requestModelDelete2, "https"),
|
||||
|
718
test/codegen/ruby_faraday_codegen_test.dart
Normal file
718
test/codegen/ruby_faraday_codegen_test.dart
Normal file
@ -0,0 +1,718 @@
|
||||
import 'package:apidash/codegen/codegen.dart';
|
||||
import 'package:apidash/consts.dart';
|
||||
import 'package:test/test.dart';
|
||||
import '../request_models.dart';
|
||||
|
||||
void main() {
|
||||
final codeGen = Codegen();
|
||||
|
||||
group('GET Request', () {
|
||||
test('GET 1', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet1, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('GET 2', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/country/data")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
req.params = {
|
||||
"code" => "US",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet2, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('GET 3', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/country/data")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
req.params = {
|
||||
"code" => "IND",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet3, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('GET 4', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/humanize/social")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
req.params = {
|
||||
"num" => "8700000",
|
||||
"digits" => "3",
|
||||
"system" => "SS",
|
||||
"add_space" => "true",
|
||||
"trailing_zeros" => "true",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet4, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('GET 5', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
req.headers = {
|
||||
"User-Agent" => "Test Agent",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet5, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('GET 6', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
req.headers = {
|
||||
"User-Agent" => "Test Agent",
|
||||
}
|
||||
req.params = {
|
||||
"raw" => "true",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet6, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('GET 7', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet7, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('GET 8', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.github.com/repos/foss42/apidash")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
req.headers = {
|
||||
"User-Agent" => "Test Agent",
|
||||
}
|
||||
req.params = {
|
||||
"raw" => "true",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet8, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('GET 9', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/humanize/social")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
req.params = {
|
||||
"num" => "8700000",
|
||||
"add_space" => "true",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet9, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('GET 10', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/humanize/social")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
req.headers = {
|
||||
"User-Agent" => "Test Agent",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.rubyFaraday,
|
||||
requestModelGet10,
|
||||
"https",
|
||||
),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test('GET 11', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/humanize/social")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
req.headers = {
|
||||
"User-Agent" => "Test Agent",
|
||||
}
|
||||
req.params = {
|
||||
"num" => "8700000",
|
||||
"digits" => "3",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet11, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('GET 12', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/humanize/social")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.get(REQUEST_URL) do |req|
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelGet12, "https"), expectedCode);
|
||||
});
|
||||
});
|
||||
|
||||
group('HEAD Request', () {
|
||||
test('HEAD 1', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.head(REQUEST_URL) do |req|
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelHead1, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('HEAD 2', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("http://api.apidash.dev")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.head(REQUEST_URL) do |req|
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelHead2, "http"), expectedCode);
|
||||
});
|
||||
});
|
||||
|
||||
group('POST Request', () {
|
||||
test('POST 1', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/case/lower")
|
||||
|
||||
PAYLOAD = <<HEREDOC
|
||||
{
|
||||
"text": "I LOVE Flutter"
|
||||
}
|
||||
HEREDOC
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.post(REQUEST_URL, PAYLOAD) do |req|
|
||||
req.headers = {
|
||||
"Content-Type" => "text/plain",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost1, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test('POST 2', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/case/lower")
|
||||
|
||||
PAYLOAD = <<HEREDOC
|
||||
{
|
||||
"text": "I LOVE Flutter",
|
||||
"flag": null,
|
||||
"male": true,
|
||||
"female": false,
|
||||
"no": 1.2,
|
||||
"arr": ["null", "true", "false", null]
|
||||
}
|
||||
HEREDOC
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.post(REQUEST_URL, PAYLOAD) do |req|
|
||||
req.headers = {
|
||||
"Content-Type" => "application/json",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost2, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test('POST 3', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/case/lower")
|
||||
|
||||
PAYLOAD = <<HEREDOC
|
||||
{
|
||||
"text": "I LOVE Flutter"
|
||||
}
|
||||
HEREDOC
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.post(REQUEST_URL, PAYLOAD) do |req|
|
||||
req.headers = {
|
||||
"User-Agent" => "Test Agent",
|
||||
"Content-Type" => "application/json",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost3, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
|
||||
test('POST 4', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/io/form")
|
||||
|
||||
PAYLOAD = URI.encode_www_form({
|
||||
"text" => "API",
|
||||
"sep" => "|",
|
||||
"times" => "3",
|
||||
})
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.post(REQUEST_URL, PAYLOAD) do |req|
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(
|
||||
CodegenLanguage.rubyFaraday,
|
||||
requestModelPost4,
|
||||
"https",
|
||||
),
|
||||
expectedCode);
|
||||
});
|
||||
test('POST 5', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/io/form")
|
||||
|
||||
PAYLOAD = URI.encode_www_form({
|
||||
"text" => "API",
|
||||
"sep" => "|",
|
||||
"times" => "3",
|
||||
})
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.post(REQUEST_URL, PAYLOAD) do |req|
|
||||
req.headers = {
|
||||
"User-Agent" => "Test Agent",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost5, "https"), expectedCode);
|
||||
});
|
||||
test('POST 6', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
require 'faraday/multipart'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/io/img")
|
||||
|
||||
PAYLOAD = {
|
||||
"token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"),
|
||||
"imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"),
|
||||
}
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
faraday.request :multipart
|
||||
end
|
||||
|
||||
response = conn.post(REQUEST_URL, PAYLOAD) do |req|
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost6, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test('POST 7', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
require 'faraday/multipart'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/io/img")
|
||||
|
||||
PAYLOAD = {
|
||||
"token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"),
|
||||
"imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"),
|
||||
}
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
faraday.request :multipart
|
||||
end
|
||||
|
||||
response = conn.post(REQUEST_URL, PAYLOAD) do |req|
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost7, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
test('POST 8', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/io/form")
|
||||
|
||||
PAYLOAD = URI.encode_www_form({
|
||||
"text" => "API",
|
||||
"sep" => "|",
|
||||
"times" => "3",
|
||||
})
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.post(REQUEST_URL, PAYLOAD) do |req|
|
||||
req.params = {
|
||||
"size" => "2",
|
||||
"len" => "3",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost8, "https"), expectedCode);
|
||||
});
|
||||
test('POST 9', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
require 'faraday/multipart'
|
||||
|
||||
REQUEST_URL = URI("https://api.apidash.dev/io/img")
|
||||
|
||||
PAYLOAD = {
|
||||
"token" => Faraday::Multipart::ParamPart.new("xyz", "text/plain"),
|
||||
"imfile" => Faraday::Multipart::FilePart.new("/Documents/up/1.png", "application/octet-stream"),
|
||||
}
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
faraday.request :multipart
|
||||
end
|
||||
|
||||
response = conn.post(REQUEST_URL, PAYLOAD) do |req|
|
||||
req.headers = {
|
||||
"User-Agent" => "Test Agent",
|
||||
"Keep-Alive" => "true",
|
||||
}
|
||||
req.params = {
|
||||
"size" => "2",
|
||||
"len" => "3",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPost9, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
|
||||
group('PUT Request', () {
|
||||
test('PUT 1', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://reqres.in/api/users/2")
|
||||
|
||||
PAYLOAD = <<HEREDOC
|
||||
{
|
||||
"name": "morpheus",
|
||||
"job": "zion resident"
|
||||
}
|
||||
HEREDOC
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.put(REQUEST_URL, PAYLOAD) do |req|
|
||||
req.headers = {
|
||||
"Content-Type" => "application/json",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPut1, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
|
||||
group('PATCH Request', () {
|
||||
test('PATCH 1', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://reqres.in/api/users/2")
|
||||
|
||||
PAYLOAD = <<HEREDOC
|
||||
{
|
||||
"name": "marfeus",
|
||||
"job": "accountant"
|
||||
}
|
||||
HEREDOC
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.patch(REQUEST_URL, PAYLOAD) do |req|
|
||||
req.headers = {
|
||||
"Content-Type" => "application/json",
|
||||
}
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelPatch1, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
|
||||
group('DELETE Request', () {
|
||||
test('DELETE 1', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://reqres.in/api/users/2")
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.delete(REQUEST_URL) do |req|
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelDelete1, "https"), expectedCode);
|
||||
});
|
||||
|
||||
test('DELETE 2', () {
|
||||
const expectedCode = r"""require 'uri'
|
||||
require 'faraday'
|
||||
|
||||
REQUEST_URL = URI("https://reqres.in/api/users/2")
|
||||
|
||||
PAYLOAD = <<HEREDOC
|
||||
{
|
||||
"name": "marfeus",
|
||||
"job": "accountant"
|
||||
}
|
||||
HEREDOC
|
||||
|
||||
conn = Faraday.new do |faraday|
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
response = conn.delete(REQUEST_URL) do |req|
|
||||
req.headers = {
|
||||
"Content-Type" => "application/json",
|
||||
}
|
||||
req.body = PAYLOAD
|
||||
end
|
||||
|
||||
puts "Status Code: #{response.status}"
|
||||
puts "Response Body: #{response.body}"
|
||||
""";
|
||||
expect(
|
||||
codeGen.getCode(CodegenLanguage.rubyFaraday, requestModelDelete2, "https"),
|
||||
expectedCode);
|
||||
});
|
||||
});
|
||||
}
|
614
test/providers/ui_providers_test.dart
Normal file
614
test/providers/ui_providers_test.dart
Normal file
@ -0,0 +1,614 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:apidash/providers/providers.dart';
|
||||
import 'package:apidash/screens/dashboard.dart';
|
||||
import 'package:apidash/screens/home_page/collection_pane.dart';
|
||||
import 'package:apidash/screens/home_page/editor_pane/details_card/code_pane.dart';
|
||||
import 'package:apidash/screens/home_page/editor_pane/details_card/response_pane.dart';
|
||||
import 'package:apidash/screens/home_page/editor_pane/editor_default.dart';
|
||||
import 'package:apidash/screens/home_page/editor_pane/editor_pane.dart';
|
||||
import 'package:apidash/screens/home_page/editor_pane/url_card.dart';
|
||||
import 'package:apidash/screens/home_page/home_page.dart';
|
||||
import 'package:apidash/screens/intro_page.dart';
|
||||
import 'package:apidash/screens/settings_page.dart';
|
||||
import 'package:apidash/services/hive_services.dart';
|
||||
import 'package:apidash/widgets/response_widgets.dart';
|
||||
import 'package:apidash/widgets/textfields.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../test_consts.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
setUp(() async {
|
||||
const MethodChannel channel =
|
||||
MethodChannel('plugins.flutter.io/path_provider');
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(channel, (MethodCall methodCall) async {
|
||||
if (methodCall.method == 'getApplicationDocumentsDirectory') {
|
||||
// Create a mock app doc directory for testing
|
||||
Directory tempDir =
|
||||
await Directory.systemTemp.createTemp('mock_app_doc_dir');
|
||||
return tempDir.path; // Return the path to the mock directory
|
||||
}
|
||||
return null;
|
||||
});
|
||||
await openBoxes();
|
||||
});
|
||||
|
||||
group('Testing navRailIndexStateProvider', () {
|
||||
testWidgets('Dashboard should display correct initial page',
|
||||
(tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Dashboard(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Verify that the HomePage is displayed initially
|
||||
expect(find.byType(HomePage), findsOneWidget);
|
||||
expect(find.byType(IntroPage), findsNothing);
|
||||
expect(find.byType(SettingsPage), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
"Dashboard should display IntroPage when navRailIndexStateProvider is 1",
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
navRailIndexStateProvider.overrideWith((ref) => 1),
|
||||
],
|
||||
child: const MaterialApp(
|
||||
home: Dashboard(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Verify that the IntroPage is displayed
|
||||
expect(find.byType(IntroPage), findsOneWidget);
|
||||
expect(find.byType(HomePage), findsNothing);
|
||||
expect(find.byType(SettingsPage), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
"Dashboard should display SettingsPage when navRailIndexStateProvider is 2",
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
overrides: [
|
||||
navRailIndexStateProvider.overrideWith((ref) => 2),
|
||||
],
|
||||
child: const MaterialApp(
|
||||
home: Dashboard(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Verify that the SettingsPage is displayed
|
||||
expect(find.byType(SettingsPage), findsOneWidget);
|
||||
expect(find.byType(IntroPage), findsNothing);
|
||||
expect(find.byType(HomePage), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'navRailIndexStateProvider should update when icon button is pressed',
|
||||
(tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Dashboard(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Tap on the Intro icon
|
||||
await tester.tap(find.byIcon(Icons.help_outline));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that the navRailIndexStateProvider is updated
|
||||
final dashboard = tester.element(find.byType(Dashboard));
|
||||
final container = ProviderScope.containerOf(dashboard);
|
||||
expect(container.read(navRailIndexStateProvider), 1);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'navRailIndexStateProvider should persist across widget rebuilds',
|
||||
(tester) async {
|
||||
// Pump the initial widget tree
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Dashboard(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Tap on the Settings icon to change the index to 2
|
||||
await tester.tap(find.byIcon(Icons.settings_outlined));
|
||||
await tester.pump();
|
||||
|
||||
// Rebuild the widget tree with the same ProviderScope
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Dashboard(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Verify that the navRailIndexStateProvider still has the updated value
|
||||
final dashboard = tester.element(find.byType(Dashboard));
|
||||
final container = ProviderScope.containerOf(dashboard);
|
||||
expect(container.read(navRailIndexStateProvider), 2);
|
||||
|
||||
// Verify that the SettingsPage is still displayed after the rebuild
|
||||
expect(find.byType(SettingsPage), findsOneWidget);
|
||||
expect(find.byType(IntroPage), findsNothing);
|
||||
expect(find.byType(HomePage), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'UI should update correctly when navRailIndexStateProvider changes',
|
||||
(tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Dashboard(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Grab the Dashboard widget and its ProviderContainer
|
||||
final dashboard = tester.element(find.byType(Dashboard));
|
||||
final container = ProviderScope.containerOf(dashboard);
|
||||
|
||||
// Go to IntroPage
|
||||
container.read(navRailIndexStateProvider.notifier).state = 1;
|
||||
await tester.pump();
|
||||
|
||||
// Verify that the IntroPage is displayed
|
||||
expect(find.byType(IntroPage), findsOneWidget);
|
||||
// Verify that the selected icon is the filled version (selectedIcon)
|
||||
expect(find.byIcon(Icons.help), findsOneWidget);
|
||||
|
||||
// Go to SettingsPage
|
||||
container.read(navRailIndexStateProvider.notifier).state = 2;
|
||||
await tester.pump();
|
||||
|
||||
// Verify that the SettingsPage is displayed
|
||||
expect(find.byType(SettingsPage), findsOneWidget);
|
||||
// Verify that the selected icon is the filled version (selectedIcon)
|
||||
expect(find.byIcon(Icons.settings), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'navRailIndexStateProvider should be disposed when Dashboard is removed',
|
||||
(tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Dashboard(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Grab the Dashboard widget and its ProviderContainer
|
||||
final dashboard = tester.element(find.byType(Dashboard));
|
||||
final container = ProviderScope.containerOf(dashboard);
|
||||
|
||||
// Pumping a different widget to remove the Dashboard from the widget tree
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
home: Scaffold(body: Text('Different Widget')),
|
||||
),
|
||||
);
|
||||
|
||||
// Verify that the ProviderContainer has been disposed
|
||||
// by trying to read from disposed container
|
||||
bool isDisposed = false;
|
||||
try {
|
||||
container.read(navRailIndexStateProvider);
|
||||
} catch (e) {
|
||||
isDisposed = true;
|
||||
}
|
||||
expect(isDisposed, true);
|
||||
});
|
||||
});
|
||||
|
||||
group("Testing selectedIdEditStateProvider", () {
|
||||
testWidgets('It should have an initial value of null', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Scaffold(
|
||||
body: CollectionPane(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Verify that the initial value is null
|
||||
final collectionPane = tester.element(find.byType(CollectionPane));
|
||||
final container = ProviderScope.containerOf(collectionPane);
|
||||
expect(container.read(selectedIdEditStateProvider), null);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'selectedIdEditStateProvider should not be null after rename button has been tapped',
|
||||
(tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Scaffold(
|
||||
body: CollectionPane(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Tap on the three dots to open the request card menu
|
||||
await tester.tap(find.byType(RequestList));
|
||||
await tester.pump();
|
||||
await tester.tap(find.byType(RequestItem));
|
||||
await tester.pump();
|
||||
await tester.tap(find.byIcon(Icons.more_vert).first);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Tap on the "Rename" option in the menu
|
||||
await tester.tap(find.text('Rename'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Verify that the selectedIdEditStateProvider is not null
|
||||
final collectionPane = tester.element(find.byType(CollectionPane));
|
||||
final container = ProviderScope.containerOf(collectionPane);
|
||||
expect(container.read(selectedIdEditStateProvider), isNotNull);
|
||||
expect((container.read(selectedIdEditStateProvider)).runtimeType, String);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'It should be set back to null when user taps outside name editor',
|
||||
(tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Scaffold(
|
||||
body: CollectionPane(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Grab the CollectionPane widget and its ProviderContainer
|
||||
final collectionPane = tester.element(find.byType(CollectionPane));
|
||||
final container = ProviderScope.containerOf(collectionPane);
|
||||
|
||||
// Tap on the three dots to open the request card menu
|
||||
await tester.tap(find.byType(RequestList));
|
||||
await tester.pump();
|
||||
await tester.tap(find.byType(RequestItem));
|
||||
await tester.pump();
|
||||
await tester.tap(find.byIcon(Icons.more_vert).first);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Tap on the "Rename" option in the menu
|
||||
await tester.tap(find.text('Rename'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Verify that the selectedIdEditStateProvider is not null
|
||||
expect(container.read(selectedIdEditStateProvider), isNotNull);
|
||||
expect((container.read(selectedIdEditStateProvider)).runtimeType, String);
|
||||
|
||||
// Tap on the screen to simulate tapping outside the name editor
|
||||
await tester.tap(find.byType(CollectionPane));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Verify that the selectedIdEditStateProvider is null
|
||||
expect(container.read(selectedIdEditStateProvider), null);
|
||||
});
|
||||
testWidgets("It should be properly disposed", (tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Scaffold(
|
||||
body: CollectionPane(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Grab the Dashboard widget and its ProviderContainer
|
||||
final collectionPane = tester.element(find.byType(CollectionPane));
|
||||
final container = ProviderScope.containerOf(collectionPane);
|
||||
|
||||
// Pumping a different widget to remove the CollectionPane from the widget tree
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
home: Scaffold(body: Text('Foo')),
|
||||
),
|
||||
);
|
||||
|
||||
// Verify that the ProviderContainer has been disposed
|
||||
// by trying to read from disposed container
|
||||
bool isDisposed = false;
|
||||
try {
|
||||
container.read(selectedIdEditStateProvider);
|
||||
} catch (e) {
|
||||
isDisposed = true;
|
||||
}
|
||||
expect(isDisposed, true);
|
||||
});
|
||||
});
|
||||
|
||||
group('Testing codePaneVisibleStateProvider', () {
|
||||
testWidgets("It should have have an initial value of false",
|
||||
(tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: RequestEditorPane(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Verify that the initial value is false
|
||||
final editorPane = tester.element(find.byType(RequestEditorPane));
|
||||
final container = ProviderScope.containerOf(editorPane);
|
||||
expect(container.read(codePaneVisibleStateProvider), false);
|
||||
});
|
||||
|
||||
testWidgets("When state is false ResponsePane should be visible",
|
||||
(tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: RequestEditorPane(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.byType(RequestEditorDefault), findsOneWidget);
|
||||
|
||||
// Tap on the "Plus New" button
|
||||
Finder plusNewButton = find.descendant(
|
||||
of: find.byType(RequestEditorDefault),
|
||||
matching: find.byType(ElevatedButton),
|
||||
);
|
||||
await tester.tap(plusNewButton);
|
||||
await tester.pump();
|
||||
|
||||
// Verify that NotSentWidget is visible
|
||||
expect(find.byType(NotSentWidget), findsOneWidget);
|
||||
|
||||
// Add some data in URLTextField
|
||||
Finder field = find.descendant(
|
||||
of: find.byType(URLField),
|
||||
matching: find.byType(TextFormField),
|
||||
);
|
||||
await tester.enterText(field, kTestUrl);
|
||||
await tester.pump();
|
||||
|
||||
// Tap on the "Send" button
|
||||
Finder sendButton = find.byType(SendButton);
|
||||
await tester.tap(sendButton);
|
||||
await tester.pump();
|
||||
|
||||
final editorPane = tester.element(find.byType(RequestEditorPane));
|
||||
final container = ProviderScope.containerOf(editorPane);
|
||||
expect(container.read(codePaneVisibleStateProvider), false);
|
||||
expect(find.byType(ResponsePane), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets("When state is true CodePane should be visible",
|
||||
(tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Scaffold(
|
||||
body: RequestEditorPane(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.byType(RequestEditorDefault), findsOneWidget);
|
||||
|
||||
// Tap on the "Plus New" button
|
||||
Finder plusNewButton = find.descendant(
|
||||
of: find.byType(RequestEditorDefault),
|
||||
matching: find.byType(ElevatedButton),
|
||||
);
|
||||
await tester.tap(plusNewButton);
|
||||
await tester.pump();
|
||||
|
||||
// Verify that NotSentWidget is visible
|
||||
expect(find.byType(NotSentWidget), findsOneWidget);
|
||||
|
||||
// Add some data in URLTextField
|
||||
Finder field = find.descendant(
|
||||
of: find.byType(URLField),
|
||||
matching: find.byType(TextFormField),
|
||||
);
|
||||
await tester.enterText(field, kTestUrl);
|
||||
await tester.pump();
|
||||
|
||||
// Tap on the "Send" button
|
||||
Finder sendButton = find.byType(SendButton);
|
||||
await tester.tap(sendButton);
|
||||
await tester.pump();
|
||||
|
||||
final editorPane = tester.element(find.byType(RequestEditorPane));
|
||||
final container = ProviderScope.containerOf(editorPane);
|
||||
// Change codePaneVisibleStateProvider state to true
|
||||
container.read(codePaneVisibleStateProvider.notifier).state = true;
|
||||
await tester.pump();
|
||||
|
||||
// Verify that the CodePane is visible
|
||||
expect(container.read(codePaneVisibleStateProvider), true);
|
||||
expect(find.byType(CodePane), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets("Hide/View Code button toggles the state", (tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Scaffold(
|
||||
body: RequestEditorPane(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.byType(RequestEditorDefault), findsOneWidget);
|
||||
|
||||
// Tap on the "Plus New" button
|
||||
Finder plusNewButton = find.descendant(
|
||||
of: find.byType(RequestEditorDefault),
|
||||
matching: find.byType(ElevatedButton),
|
||||
);
|
||||
await tester.tap(plusNewButton);
|
||||
await tester.pump();
|
||||
|
||||
// Verify that NotSentWidget is visible
|
||||
expect(find.byType(NotSentWidget), findsOneWidget);
|
||||
|
||||
// Add some data in URLTextField
|
||||
Finder field = find.descendant(
|
||||
of: find.byType(URLField),
|
||||
matching: find.byType(TextFormField),
|
||||
);
|
||||
await tester.enterText(field, kTestUrl);
|
||||
await tester.pump();
|
||||
|
||||
// Tap on the "Send" button
|
||||
Finder sendButton = find.byType(SendButton);
|
||||
await tester.tap(sendButton);
|
||||
await tester.pump();
|
||||
|
||||
final editorPane = tester.element(find.byType(RequestEditorPane));
|
||||
final container = ProviderScope.containerOf(editorPane);
|
||||
final bool currentValue = container.read(codePaneVisibleStateProvider);
|
||||
|
||||
// Click on View Code button
|
||||
await tester.tap(find.byIcon(Icons.code_rounded));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that the state value has changed
|
||||
expect(container.read(codePaneVisibleStateProvider), !currentValue);
|
||||
final bool newValue = container.read(codePaneVisibleStateProvider);
|
||||
|
||||
// Click on Hide Code button
|
||||
await tester.tap(find.byIcon(Icons.code_off_rounded));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that the state value has changed
|
||||
expect(container.read(codePaneVisibleStateProvider), !newValue);
|
||||
});
|
||||
|
||||
testWidgets("That state persists across widget rebuilds", (tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Scaffold(
|
||||
body: RequestEditorPane(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.byType(RequestEditorDefault), findsOneWidget);
|
||||
|
||||
// Tap on the "Plus New" button
|
||||
Finder plusNewButton = find.descendant(
|
||||
of: find.byType(RequestEditorDefault),
|
||||
matching: find.byType(ElevatedButton),
|
||||
);
|
||||
await tester.tap(plusNewButton);
|
||||
await tester.pump();
|
||||
|
||||
// Verify that NotSentWidget is visible
|
||||
expect(find.byType(NotSentWidget), findsOneWidget);
|
||||
|
||||
// Add some data in URLTextField
|
||||
Finder field = find.descendant(
|
||||
of: find.byType(URLField),
|
||||
matching: find.byType(TextFormField),
|
||||
);
|
||||
await tester.enterText(field, kTestUrl);
|
||||
await tester.pump();
|
||||
|
||||
// Tap on the "Send" button
|
||||
Finder sendButton = find.byType(SendButton);
|
||||
await tester.tap(sendButton);
|
||||
await tester.pump();
|
||||
|
||||
final editorPane = tester.element(find.byType(RequestEditorPane));
|
||||
final container = ProviderScope.containerOf(editorPane);
|
||||
final bool currentValue = container.read(codePaneVisibleStateProvider);
|
||||
|
||||
// Click on View Code button
|
||||
await tester.tap(find.byIcon(Icons.code_rounded));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that the state value has changed
|
||||
expect(container.read(codePaneVisibleStateProvider), !currentValue);
|
||||
bool matcher = !currentValue;
|
||||
|
||||
// Rebuild the widget tree
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Scaffold(
|
||||
body: RequestEditorPane(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Verify that the value of codePaneVisibleStateProvider is still true
|
||||
final containerAfterRebuild = ProviderScope.containerOf(editorPane);
|
||||
bool actual = containerAfterRebuild.read(codePaneVisibleStateProvider);
|
||||
expect(actual, matcher);
|
||||
});
|
||||
|
||||
testWidgets("That it is properly disposed", (tester) async {
|
||||
await tester.pumpWidget(
|
||||
const ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Scaffold(
|
||||
body: RequestEditorPane(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Verify that codePaneVisibleStateProvider is present
|
||||
final editorPane = tester.element(find.byType(RequestEditorPane));
|
||||
final container = ProviderScope.containerOf(editorPane);
|
||||
expect(container.read(codePaneVisibleStateProvider).runtimeType, bool);
|
||||
|
||||
// Update the widget tree to dispose the provider
|
||||
await tester.pumpWidget(const MaterialApp());
|
||||
|
||||
// Verify that the provider was disposed
|
||||
expect(() => container.read(codePaneVisibleStateProvider),
|
||||
throwsA(isA<StateError>()));
|
||||
expect(
|
||||
() => container.read(codePaneVisibleStateProvider),
|
||||
throwsA(
|
||||
isA<StateError>().having(
|
||||
(e) => e.message,
|
||||
'message',
|
||||
contains('was already disposed'),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
final kThemeDataDark = ThemeData(
|
||||
useMaterial3: true,
|
||||
@ -13,6 +13,8 @@ final kThemeDataLight = ThemeData(
|
||||
brightness: Brightness.light,
|
||||
);
|
||||
|
||||
const kTestUrl = 'https://api.apidash.dev';
|
||||
|
||||
Uint8List kBodyBytesJpeg = Uint8List.fromList([
|
||||
255,
|
||||
216,
|
||||
|
@ -1,21 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:apidash/widgets/form_data_field.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Testing for Form Data Widget', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
title: 'Form Data Field Widget',
|
||||
home: Scaffold(
|
||||
body: FormDataField(
|
||||
keyId: "1",
|
||||
initialValue: "Test Field",
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text("Test Field"), findsOneWidget);
|
||||
});
|
||||
}
|
@ -5,6 +5,7 @@ import 'package:apidash/consts.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:printing/printing.dart' show PdfPreview;
|
||||
import 'package:flutter_svg/flutter_svg.dart' show SvgPicture;
|
||||
import 'package:apidash/widgets/video_previewer.dart';
|
||||
import '../test_consts.dart';
|
||||
|
||||
void main() {
|
||||
@ -63,10 +64,7 @@ void main() {
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(
|
||||
find.text("${kMimeTypeRaiseIssueStart}video/H264$kMimeTypeRaiseIssue"),
|
||||
findsOneWidget);
|
||||
expect(find.byType(VideoPreviewer), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Testing when type/subtype is model/step+xml', (tester) async {
|
||||
|
@ -21,7 +21,6 @@ void main() {
|
||||
);
|
||||
|
||||
expect(find.byType(Center), findsAtLeastNWidgets(1));
|
||||
expect(find.text('Request'), findsOneWidget);
|
||||
expect(find.text('Hide Code'), findsOneWidget);
|
||||
expect(find.text('View Code'), findsNothing);
|
||||
expect(find.text('URL Params'), findsOneWidget);
|
||||
@ -52,7 +51,6 @@ void main() {
|
||||
);
|
||||
|
||||
expect(find.byType(Center), findsAtLeastNWidgets(1));
|
||||
expect(find.text('Request'), findsOneWidget);
|
||||
expect(find.text('Hide Code'), findsOneWidget);
|
||||
expect(find.text('View Code'), findsNothing);
|
||||
expect(find.text('URL Params'), findsOneWidget);
|
||||
@ -83,7 +81,6 @@ void main() {
|
||||
);
|
||||
|
||||
expect(find.byType(Center), findsAtLeastNWidgets(1));
|
||||
expect(find.text('Request'), findsOneWidget);
|
||||
expect(find.text('Hide Code'), findsNothing);
|
||||
expect(find.text('View Code'), findsOneWidget);
|
||||
expect(find.text('URL Params'), findsOneWidget);
|
||||
@ -117,7 +114,6 @@ void main() {
|
||||
);
|
||||
|
||||
expect(find.byType(Center), findsAtLeastNWidgets(1));
|
||||
expect(find.text('Request'), findsOneWidget);
|
||||
expect(find.text('URL Params'), findsOneWidget);
|
||||
expect(find.text('Headers'), findsOneWidget);
|
||||
expect(find.text('Body'), findsOneWidget);
|
||||
|
@ -10,13 +10,15 @@ import 'package:apidash/models/models.dart';
|
||||
import '../test_consts.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Testing Sending Widget', (tester) async {
|
||||
testWidgets('Testing Sending Widget Without Timer', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
title: 'Send',
|
||||
theme: kThemeDataDark,
|
||||
home: const Scaffold(
|
||||
body: SendingWidget(),
|
||||
body: SendingWidget(
|
||||
startSendingTime: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -24,6 +26,26 @@ void main() {
|
||||
expect(find.byType(Lottie), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Testing Sending Widget With Timer', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
title: 'Send',
|
||||
theme: kThemeDataDark,
|
||||
home: Scaffold(
|
||||
body: SendingWidget(
|
||||
startSendingTime: DateTime.now(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.text('Time elapsed: 0 ms'), findsOneWidget);
|
||||
expect(find.byType(Lottie), findsOneWidget);
|
||||
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
|
||||
expect(find.text('Time elapsed: 1.00 s'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Testing Not Sent Widget', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
@ -52,11 +74,8 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.byType(RichText), findsAtLeastNWidgets(1));
|
||||
expect(
|
||||
find.textContaining("Response (", findRichText: true), findsOneWidget);
|
||||
expect(find.text('Hi'), findsOneWidget);
|
||||
expect(find.textContaining("200", findRichText: true), findsOneWidget);
|
||||
expect(find.textContaining("Hi", findRichText: true), findsOneWidget);
|
||||
expect(find.text(humanizeDuration(const Duration(microseconds: 23))),
|
||||
findsOneWidget);
|
||||
});
|
||||
@ -73,7 +92,7 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
expect(find.text('Body'), findsOneWidget);
|
||||
expect(find.text('Response Body'), findsOneWidget);
|
||||
expect(find.text('Headers'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('Headers'));
|
||||
@ -81,7 +100,7 @@ void main() {
|
||||
|
||||
expect(find.text('first'), findsNothing);
|
||||
expect(find.text('second'), findsOneWidget);
|
||||
await tester.tap(find.text('Body'));
|
||||
await tester.tap(find.text('Response Body'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('first'), findsOneWidget);
|
||||
|
Reference in New Issue
Block a user