diff --git a/lib/codegen/dart/dio.dart b/lib/codegen/dart/dio.dart index c4a7ed8e6..c2971a214 100644 --- a/lib/codegen/dart/dio.dart +++ b/lib/codegen/dart/dio.dart @@ -33,7 +33,7 @@ class DartDioCodeGen { String generatedDartCode({ required String url, required HTTPVerb method, - required Map queryParams, + required Map queryParams, required Map headers, required String? body, required ContentType contentType, diff --git a/lib/codegen/dart/http.dart b/lib/codegen/dart/http.dart index 42c44ecb3..443a1e0e1 100644 --- a/lib/codegen/dart/http.dart +++ b/lib/codegen/dart/http.dart @@ -35,7 +35,7 @@ class DartHttpCodeGen { String generatedDartCode({ required String url, required HTTPVerb method, - required Map queryParams, + required Map queryParams, required Map headers, required ContentType contentType, required String? body, diff --git a/lib/models/request_model.dart b/lib/models/request_model.dart index a8d3569a4..1b91913b3 100644 --- a/lib/models/request_model.dart +++ b/lib/models/request_model.dart @@ -6,6 +6,8 @@ import '../utils/utils.dart' rowsToFormDataMapList, mapToRows, rowsToMap, + requestMapToRows, + rowsToRequestMap, getEnabledRows; import '../consts.dart'; import 'models.dart'; @@ -57,10 +59,10 @@ class RequestModel { Map get enabledHeadersMap => rowsToMap(enabledRequestHeaders) ?? {}; - Map get enabledParamsMap => - rowsToMap(enabledRequestParams) ?? {}; + Map get enabledParamsMap => + rowsToRequestMap(enabledRequestParams) ?? {}; Map get headersMap => rowsToMap(requestHeaders) ?? {}; - Map get paramsMap => rowsToMap(requestParams) ?? {}; + Map get paramsMap => rowsToRequestMap(requestParams) ?? {}; List> get formDataMapList => rowsToFormDataMapList(requestFormDataList) ?? []; @@ -184,7 +186,7 @@ class RequestModel { ? mapToRows(Map.from(requestHeaders)) : null, requestParams: requestParams != null - ? mapToRows(Map.from(requestParams)) + ? requestMapToRows(Map.from(requestParams)) : null, isHeaderEnabledList: isHeaderEnabledList, isParamEnabledList: isParamEnabledList, @@ -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, diff --git a/lib/utils/convert_utils.dart b/lib/utils/convert_utils.dart index bc704af99..92879a5a7 100644 --- a/lib/utils/convert_utils.dart +++ b/lib/utils/convert_utils.dart @@ -61,6 +61,37 @@ String padMultilineString(String text, int padding, return lines.join("\n"); } +Map? rowsToRequestMap(List? kvRows) { + if (kvRows == null) { + return null; + } + Map> 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? requestMapToRows(Map? requestMap) { + if (requestMap == null) { + return null; + } + List finalRows = []; + for (var key in requestMap.keys) { + List elementList = requestMap[key] is List ? requestMap[key] : [requestMap[key]]; + for (var element in elementList) { + finalRows.add(NameValueModel(name: key, value: element)); + } + } + return finalRows; +} + Map? rowsToMap(List? kvRows, {bool isHeader = false}) { if (kvRows == null) { diff --git a/lib/utils/har_utils.dart b/lib/utils/har_utils.dart index b5e1de72f..748686d9c 100644 --- a/lib/utils/har_utils.dart +++ b/lib/utils/har_utils.dart @@ -99,14 +99,16 @@ Map requestModelToHARJsonRequest( json["queryString"] = []; json["headers"] = []; - var params = uri.queryParameters; + Map> 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); } } diff --git a/lib/utils/http_utils.dart b/lib/utils/http_utils.dart index 63aa6181a..245308a6b 100644 --- a/lib/utils/http_utils.dart +++ b/lib/utils/http_utils.dart @@ -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) { @@ -88,12 +88,16 @@ String stripUrlParams(String url) { uri = uri.removeFragment(); } - Map? queryParams = rowsToMap(requestParams); - if (queryParams != null) { - if (uri.hasQuery) { - Map urlQueryParams = uri.queryParameters; - queryParams = mergeMaps(urlQueryParams, queryParams); - } + Map> queryParams = uri.queryParametersAll; + + Map? requestQueryParams = rowsToRequestMap(requestParams); + if (requestQueryParams != null) { + Map> queryParamsList = requestQueryParams.map((key, value) { + return MapEntry(key, List.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); diff --git a/test/codegen/curl_codegen_test.dart b/test/codegen/curl_codegen_test.dart index 4481e8194..13f145e22 100644 --- a/test/codegen/curl_codegen_test.dart +++ b/test/codegen/curl_codegen_test.dart @@ -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); }); diff --git a/test/models/request_model_test.dart b/test/models/request_model_test.dart index 1bb40ec72..e8d5475ed 100644 --- a/test/models/request_model_test.dart +++ b/test/models/request_model_test.dart @@ -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" @@ -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" @@ -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" @@ -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": '''{ @@ -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}', @@ -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); diff --git a/test/request_models.dart b/test/request_models.dart index 0c3d85e2a..fb44ef59b 100644 --- a/test/request_models.dart +++ b/test/request_models.dart @@ -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'), ], ); diff --git a/test/utils/convert_utils_test.dart b/test/utils/convert_utils_test.dart index e996c3190..fc53208cb 100644 --- a/test/utils/convert_utils_test.dart +++ b/test/utils/convert_utils_test.dart @@ -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(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(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 value1 = {"text": ["abc", "def"], "lang": "eng", "code": "1"}; + const result1Expected = [ + 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); diff --git a/test/utils/har_utils_test.dart b/test/utils/har_utils_test.dart index 174ab1803..9664a4629 100644 --- a/test/utils/har_utils_test.dart +++ b/test/utils/har_utils_test.dart @@ -318,6 +318,21 @@ void main() { ), expectedResult); }); + test('Test requestModelToHARJsonRequest with duplicate query parameters', () { + Map 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); + }); }, ); } diff --git a/test/utils/http_utils_test.dart b/test/utils/http_utils_test.dart index 2b660fcb3..016cf3bda 100644 --- a/test/utils/http_utils_test.dart +++ b/test/utils/http_utils_test.dart @@ -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', () { @@ -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", () {