Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add feature to support url params having the same key and different values #276

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/codegen/dart/dio.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class DartDioCodeGen {
String generatedDartCode({
required String url,
required HTTPVerb method,
required Map<String, String> queryParams,
required Map<String, dynamic> queryParams,
required Map<String, String> headers,
required String? body,
required ContentType contentType,
Expand Down
2 changes: 1 addition & 1 deletion lib/codegen/dart/http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class DartHttpCodeGen {
String generatedDartCode({
required String url,
required HTTPVerb method,
required Map<String, String> queryParams,
required Map<String, dynamic> queryParams,
required Map<String, String> headers,
required ContentType contentType,
required String? body,
Expand Down
12 changes: 7 additions & 5 deletions lib/models/request_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import '../utils/utils.dart'
rowsToFormDataMapList,
mapToRows,
rowsToMap,
requestMapToRows,
rowsToRequestMap,
getEnabledRows;
import '../consts.dart';
import 'models.dart';
Expand Down Expand Up @@ -57,10 +59,10 @@ class RequestModel {

Map<String, String> get enabledHeadersMap =>
rowsToMap(enabledRequestHeaders) ?? {};
Map<String, String> get enabledParamsMap =>
rowsToMap(enabledRequestParams) ?? {};
Map<String, dynamic> get enabledParamsMap =>
rowsToRequestMap(enabledRequestParams) ?? {};
Map<String, String> get headersMap => rowsToMap(requestHeaders) ?? {};
Map<String, String> get paramsMap => rowsToMap(requestParams) ?? {};
Map<String, dynamic> get paramsMap => rowsToRequestMap(requestParams) ?? {};

List<Map<String, dynamic>> get formDataMapList =>
rowsToFormDataMapList(requestFormDataList) ?? [];
Expand Down Expand Up @@ -184,7 +186,7 @@ class RequestModel {
? mapToRows(Map<String, String>.from(requestHeaders))
: null,
requestParams: requestParams != null
? mapToRows(Map<String, String>.from(requestParams))
? requestMapToRows(Map<String, dynamic>.from(requestParams))
: null,
isHeaderEnabledList: isHeaderEnabledList,
isParamEnabledList: isParamEnabledList,
Expand All @@ -207,7 +209,7 @@ class RequestModel {
"name": name,
"description": description,
"requestHeaders": rowsToMap(requestHeaders),
"requestParams": rowsToMap(requestParams),
"requestParams": rowsToRequestMap(requestParams),
"isHeaderEnabledList": isHeaderEnabledList,
"isParamEnabledList": isParamEnabledList,
"requestBodyContentType": requestBodyContentType.name,
Expand Down
31 changes: 31 additions & 0 deletions lib/utils/convert_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,37 @@ String padMultilineString(String text, int padding,
return lines.join("\n");
}

Map<String, dynamic>? rowsToRequestMap(List<NameValueModel>? kvRows) {
if (kvRows == null) {
return null;
}
Map<String, List<String>> finalMap = {};
for (var row in kvRows) {
if (row.name.trim() != "") {
String key = row.name;
if (!finalMap.containsKey(key)) {
finalMap[key] = [];
}
finalMap[key]!.add(row.value.toString());
}
}
return finalMap.map((key, valueList) => MapEntry(key, valueList.length == 1 ? valueList[0] : valueList));
}

List<NameValueModel>? requestMapToRows(Map<String, dynamic>? requestMap) {
if (requestMap == null) {
return null;
}
List<NameValueModel> finalRows = [];
for (var key in requestMap.keys) {
List<String> elementList = requestMap[key] is List<String> ? requestMap[key] : [requestMap[key]];
for (var element in elementList) {
finalRows.add(NameValueModel(name: key, value: element));
}
}
return finalRows;
}

Map<String, String>? rowsToMap(List<NameValueModel>? kvRows,
{bool isHeader = false}) {
if (kvRows == null) {
Expand Down
12 changes: 7 additions & 5 deletions lib/utils/har_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,16 @@ Map<String, dynamic> requestModelToHARJsonRequest(
json["queryString"] = [];
json["headers"] = [];

var params = uri.queryParameters;
Map<String, List<String>> params = uri.queryParametersAll;
if (params.isNotEmpty) {
for (final k in params.keys) {
var m = {"name": k, "value": params[k]};
if (exportMode) {
m["comment"] = "";
for (final val in params[k]!) {
var m = {"name": k, "value": val};
if (exportMode) {
m["comment"] = "";
}
json["queryString"].add(m);
}
json["queryString"].add(m);
}
}

Expand Down
18 changes: 11 additions & 7 deletions lib/utils/http_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'package:collection/collection.dart' show mergeMaps;
import 'package:http_parser/http_parser.dart';
import 'package:xml/xml.dart';
import '../models/models.dart';
import 'convert_utils.dart' show rowsToMap;
import 'convert_utils.dart' show rowsToRequestMap;
import '../consts.dart';

String getRequestTitleFromUrl(String? url) {
Expand Down Expand Up @@ -88,12 +88,16 @@ String stripUrlParams(String url) {
uri = uri.removeFragment();
}

Map<String, String>? queryParams = rowsToMap(requestParams);
if (queryParams != null) {
if (uri.hasQuery) {
Map<String, String> urlQueryParams = uri.queryParameters;
queryParams = mergeMaps(urlQueryParams, queryParams);
}
Map<String, List<String>> queryParams = uri.queryParametersAll;

Map<String, dynamic>? requestQueryParams = rowsToRequestMap(requestParams);
if (requestQueryParams != null) {
Map<String, List<String>> queryParamsList = requestQueryParams.map((key, value) {
return MapEntry(key, List<String>.from(value is String ? [value] : value));
});
queryParams = mergeMaps(queryParams, queryParamsList, value: (v1, v2) => v1 + v2);
}
if (queryParams.isNotEmpty) {
uri = uri.replace(queryParameters: queryParams);
}
return (uri, null);
Expand Down
2 changes: 1 addition & 1 deletion test/codegen/curl_codegen_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void main() {

test('GET 3', () {
const expectedCode =
r"""curl --url 'https://api.apidash.dev/country/data?code=IND'""";
r"""curl --url 'https://api.apidash.dev/country/data?code=US&code=UK&code=IN&code=JP'""";
expect(curlCodeGen.getCode(requestModelGet3, "https"), expectedCode);
});

Expand Down
27 changes: 22 additions & 5 deletions test/models/request_model_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ void main() {
NameValueModel(
name: 'content-type', value: 'application/json; charset=utf-8')
],
requestParams: const [
NameValueModel(name: 'TEXT', value: 'abc')
],
requestBodyContentType: ContentType.json,
requestBody: '''{
"text":"WORLD"
Expand All @@ -76,6 +79,9 @@ void main() {
NameValueModel(
name: 'content-type', value: 'application/json; charset=utf-8')
],
requestParams: [
NameValueModel(name: 'TEXT', value: 'abc')
],
requestBodyContentType: ContentType.json,
requestBody: '''{
"text":"WORLD"
Expand All @@ -91,6 +97,9 @@ void main() {
NameValueModel(
name: 'content-type', value: 'application/json; charset=utf-8')
],
requestParams: [
NameValueModel(name: 'TEXT', value: 'abc')
],
requestBodyContentType: ContentType.json,
requestBody: '''{
"text":"WORLD"
Expand All @@ -107,7 +116,9 @@ void main() {
'content-type': 'application/json; charset=utf-8'
},
'isHeaderEnabledList': null,
'requestParams': null,
'requestParams': {
'TEXT': 'abc',
},
'isParamEnabledList': null,
"requestBodyContentType": 'json',
"requestBody": '''{
Expand Down Expand Up @@ -144,7 +155,7 @@ void main() {
"Request Tab Index: 0",
"Request Headers: [NameValueModel(name: content-length, value: 18), NameValueModel(name: content-type, value: application/json; charset=utf-8)]",
"Enabled Headers: null",
"Request Params: null",
"Request Params: [NameValueModel(name: TEXT, value: abc)]",
"Enabled Params: null",
"Request Body Content Type: ContentType.json",
'Request Body: {\n"text":"WORLD"\n}',
Expand All @@ -163,17 +174,23 @@ void main() {
NameValueModel(
name: 'content-type', value: 'application/json; charset=utf-8')
]);
expect(requestModel.enabledRequestParams, null);
expect(requestModel.enabledRequestParams, const [
NameValueModel(name: 'TEXT', value: 'abc')
]);
expect(requestModel.enabledHeadersMap, {
'content-length': '18',
'content-type': 'application/json; charset=utf-8'
});
expect(requestModel.enabledParamsMap, {});
expect(requestModel.enabledParamsMap, {
'TEXT': 'abc'
});
expect(requestModel.headersMap, {
'content-length': '18',
'content-type': 'application/json; charset=utf-8'
});
expect(requestModel.paramsMap, {});
expect(requestModel.paramsMap, {
'TEXT': 'abc'
});
expect(requestModel.formDataMapList, []);
expect(requestModel.isFormDataRequest, false);
expect(requestModel.hasContentTypeHeader, true);
Expand Down
7 changes: 4 additions & 3 deletions test/request_models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ const requestModelGet2 = RequestModel(
],
);

/// GET request model with override query params
/// GET request model with duplicate query params
const requestModelGet3 = RequestModel(
id: 'get3',
url: 'https://api.apidash.dev/country/data?code=US',
url: 'https://api.apidash.dev/country/data?code=US&code=UK',
method: HTTPVerb.get,
requestParams: [
NameValueModel(name: 'code', value: 'IND'),
NameValueModel(name: 'code', value: 'IN'),
NameValueModel(name: 'code', value: 'JP'),
],
);

Expand Down
43 changes: 43 additions & 0 deletions test/utils/convert_utils_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,49 @@ void main() {
expect(formatHeaderCase(headerText2), headerText2Expected);
});
});

group("Testing rowsToRequestMap", () {
test('Testing for null', () {
expect(rowsToRequestMap(null), null);
});
test('Testing for string KVRow values', () {
const kvRow1 = NameValueModel(name: "code", value: "IN");
expect(rowsToRequestMap([kvRow1]), {"code": "IN"});
});
test('Testing when header is false and key is in upper case', () {
const kvRow3 = <NameValueModel>[
NameValueModel(name: "TEXT", value: "ABC"),
NameValueModel(name: "version", value: 0.1),
NameValueModel(name: "month", value: 4),
];
expect(
rowsToRequestMap(kvRow3), {"TEXT": "ABC", "version": "0.1", "month": "4"});
});
test('Testing for duplicate search params', () {
const kvRow4 = <NameValueModel>[
NameValueModel(name: "TEXT", value: "ABC"),
NameValueModel(name: "TEXT", value: "DEF"),
];
expect(rowsToRequestMap(kvRow4), {"TEXT": ["ABC", "DEF"]});
});
});

group("Testing requestMapToRows", () {
test('Testing for null', () {
expect(requestMapToRows(null), null);
});
test('Testing with a map value', () {
Map<String, dynamic> value1 = {"text": ["abc", "def"], "lang": "eng", "code": "1"};
const result1Expected = <NameValueModel>[
NameValueModel(name: "text", value: "abc"),
NameValueModel(name: "text", value: "def"),
NameValueModel(name: "lang", value: "eng"),
NameValueModel(name: "code", value: "1")
];
expect(requestMapToRows(value1), result1Expected);
});
});

group("Testing rowsToMap", () {
test('Testing for null', () {
expect(rowsToMap(null), null);
Expand Down
15 changes: 15 additions & 0 deletions test/utils/har_utils_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,21 @@ void main() {
),
expectedResult);
});
test('Test requestModelToHARJsonRequest with duplicate query parameters', () {
Map<String, dynamic> expectedResult = {
'method': 'GET',
'url': 'https://api.apidash.dev/country/data?code=US&code=UK&code=IN&code=JP',
'httpVersion': 'HTTP/1.1',
'queryString': [
{'name': 'code', 'value': 'US'},
{'name': 'code', 'value': 'UK'},
{'name': 'code', 'value': 'IN'},
{'name': 'code', 'value': 'JP'},
],
'headers': []
};
expect(requestModelToHARJsonRequest(requestModelGet3), expectedResult);
});
},
);
}
11 changes: 10 additions & 1 deletion test/utils/http_utils_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ void main() {
scheme: 'https',
host: 'api.apidash.dev',
path: 'country/data',
queryParameters: {'code': 'US'});
queryParameters: {'code': ['IND', 'US']});
expect(getValidRequestUri(url6, [kvRow6]), (uri6Expected, null));
});
test('Testing getValidRequestUri when kvrow is null', () {
Expand All @@ -235,6 +235,15 @@ void main() {
queryParameters: {'code': 'US'});
expect(getValidRequestUri(url7, null), (uri7Expected, null));
});
test('Testing getValidRequestUri when passing duplicate search parameters in url as comma separated', () {
String url9 = "api.apidash.dev/country/data?code=US,IND";
Uri uri9Expected = Uri(
scheme: 'https',
host: 'api.apidash.dev',
path: 'country/data',
queryParameters: {'code': 'US,IND'});
expect(getValidRequestUri(url9, null), (uri9Expected, null));
});
});

group("Testing getResponseBodyViewOptions", () {
Expand Down