Added Kotlin OkHttp Tests and refactoring.

This commit is contained in:
mmjsmohit
2023-06-01 22:15:46 +05:30
parent d54a4473cb
commit a3ad56cb53
8 changed files with 219 additions and 143 deletions

View File

@ -8,21 +8,16 @@ import '../providers/settings_providers.dart';
import 'dart/pkg_http.dart';
class Codegen {
const Codegen({required this.codegenLanguage});
final CodegenLanguage codegenLanguage;
String? getCode(
WidgetRef ref,
CodegenLanguage codegenLanguage,
RequestModel requestModel,
String defaultUriScheme,
) {
final activeRequestModel = ref.watch(activeRequestModelProvider);
final defaultUriScheme =
ref.watch(settingsProvider.select((value) => value.defaultUriScheme));
switch (codegenLanguage) {
case CodegenLanguage.dartHttp:
return DartHttpCodeGen().getCode(activeRequestModel!, defaultUriScheme);
return DartHttpCodeGen().getCode(requestModel, defaultUriScheme);
case CodegenLanguage.kotlinOkHttp:
return KotlinOkHttpCodeGen().getCode(activeRequestModel!);
return KotlinOkHttpCodeGen().getCode(requestModel);
default:
throw ArgumentError('Invalid codegenLanguage');
}

View File

@ -69,6 +69,8 @@ val body = "${requestModel.requestBody}".toRequestBody(mediaType)\n""";
requestModel.method != HTTPVerb.head &&
requestModel.method != HTTPVerb.delete) {
result = """$result .${requestModel.method.name}(body)\n""";
} else if (requestModel.method == HTTPVerb.head) {
result = """$result .${requestModel.method.name}()\n""";
}
if (requestModel.method == HTTPVerb.delete) {
result = """$result .method("DELETE", body)\n""";

View File

@ -229,8 +229,8 @@ const kDefaultHttpMethod = HTTPVerb.get;
const kDefaultContentType = ContentType.json;
enum CodegenLanguage {
dartHttp("Dart - http"),
kotlinOkHttp("Kotlin - OkHttp");
dartHttp("Dart (http)"),
kotlinOkHttp("Kotlin (OkHttp)");
const CodegenLanguage(this.label);
final String label;

View File

@ -1,3 +1,4 @@
import 'package:apidash/utils/convert_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:apidash/providers/providers.dart';
@ -13,6 +14,8 @@ class CodePane extends ConsumerStatefulWidget {
}
class _CodePaneState extends ConsumerState<CodePane> {
final Codegen codegen = Codegen();
@override
void initState() {
super.initState();
@ -22,11 +25,13 @@ class _CodePaneState extends ConsumerState<CodePane> {
Widget build(BuildContext context) {
final CodegenLanguage codegenLanguage =
ref.watch(codegenLanguageStateProvider);
final Codegen codegen = Codegen(codegenLanguage: codegenLanguage);
final activeRequestModel = ref.watch(activeRequestModelProvider);
final defaultUriScheme =
ref.watch(settingsProvider.select((value) => value.defaultUriScheme));
final code = codegen.getCode(ref, activeRequestModel!, defaultUriScheme);
final code =
codegen.getCode(codegenLanguage, activeRequestModel!, defaultUriScheme);
if (code == null) {
return const ErrorMessage(
message: "An error was encountered while generating code. $kRaiseIssue",
@ -37,3 +42,82 @@ class _CodePaneState extends ConsumerState<CodePane> {
);
}
}
class ViewCodePane extends ConsumerStatefulWidget {
const ViewCodePane({
super.key,
required this.code,
});
final String code;
@override
ConsumerState<ConsumerStatefulWidget> createState() => _ViewCodePaneState();
}
class _ViewCodePaneState extends ConsumerState<ViewCodePane> {
@override
Widget build(BuildContext context) {
var codeTheme = Theme.of(context).brightness == Brightness.light
? kLightCodeTheme
: kDarkCodeTheme;
final textContainerdecoration = BoxDecoration(
color: Color.alphaBlend(
(Theme.of(context).brightness == Brightness.dark
? Theme.of(context).colorScheme.onPrimaryContainer
: Theme.of(context).colorScheme.primaryContainer)
.withOpacity(kForegroundOpacity),
Theme.of(context).colorScheme.surface),
border: Border.all(color: Theme.of(context).colorScheme.surfaceVariant),
borderRadius: kBorderRadius8,
);
return Padding(
padding: kP10,
child: Column(
children: [
SizedBox(
height: kHeaderHeight,
child: Row(
children: [
Expanded(
child: Text(
"Code",
style: Theme.of(context).textTheme.titleMedium,
),
),
DropdownButtonCodegenLanguage(
codegenLanguage: ref.watch(codegenLanguageStateProvider),
onChanged: (CodegenLanguage? value) {
ref
.read(codegenLanguageStateProvider.notifier)
.update((state) => value!);
},
),
CopyButton(toCopy: widget.code),
SaveInDownloadsButton(
content: stringToBytes(widget.code),
mimeType: "application/vnd.dart",
)
],
),
),
kVSpacer10,
Expanded(
child: Container(
width: double.maxFinite,
padding: kP8,
decoration: textContainerdecoration,
child: CodeGenPreviewer(
code: widget.code,
theme: codeTheme,
language: 'dart',
textStyle: kCodeStyle,
),
),
),
],
),
);
}
}

View File

@ -1,12 +1,6 @@
import 'package:apidash/widgets/dropdowns.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:highlighter/highlighter.dart' show highlight;
import 'package:apidash/consts.dart';
import 'package:apidash/utils/utils.dart';
import '../providers/ui_providers.dart';
import 'code_previewer.dart' show convert;
import 'buttons.dart';
class CodeGenPreviewer extends StatefulWidget {
const CodeGenPreviewer({
@ -103,98 +97,3 @@ List<TextSpan> generateSpans(
var spans = convert(parsed.nodes!, theme);
return spans;
}
class ViewCodePane extends StatefulWidget {
const ViewCodePane({
super.key,
required this.code,
});
final String code;
@override
State<ViewCodePane> createState() => _ViewCodePaneState();
}
class _ViewCodePaneState extends State<ViewCodePane> {
@override
Widget build(BuildContext context) {
var codeTheme = Theme.of(context).brightness == Brightness.light
? kLightCodeTheme
: kDarkCodeTheme;
final textContainerdecoration = BoxDecoration(
color: Color.alphaBlend(
(Theme.of(context).brightness == Brightness.dark
? Theme.of(context).colorScheme.onPrimaryContainer
: Theme.of(context).colorScheme.primaryContainer)
.withOpacity(kForegroundOpacity),
Theme.of(context).colorScheme.surface),
border: Border.all(color: Theme.of(context).colorScheme.surfaceVariant),
borderRadius: kBorderRadius8,
);
return Padding(
padding: kP10,
child: Column(
children: [
SizedBox(
height: kHeaderHeight,
child: Row(
children: [
Expanded(
child: Text(
"Code",
style: Theme.of(context).textTheme.titleMedium,
),
),
const DropdownButtonCodeCodegenLanguage(),
CopyButton(toCopy: widget.code),
SaveInDownloadsButton(
content: stringToBytes(widget.code),
mimeType: "application/vnd.dart",
)
],
),
),
kVSpacer10,
Expanded(
child: Container(
width: double.maxFinite,
padding: kP8,
decoration: textContainerdecoration,
child: CodeGenPreviewer(
code: widget.code,
theme: codeTheme,
language: 'dart',
textStyle: kCodeStyle,
),
),
),
],
),
);
}
}
class DropdownButtonCodeCodegenLanguage extends ConsumerStatefulWidget {
const DropdownButtonCodeCodegenLanguage({
super.key,
});
@override
ConsumerState createState() => _DropdownButtonCodeCodegenLanguageState();
}
class _DropdownButtonCodeCodegenLanguageState
extends ConsumerState<DropdownButtonCodeCodegenLanguage> {
@override
Widget build(BuildContext context) {
final requestCodeLanguage = ref.watch(codegenLanguageStateProvider);
return DropdownButtonCodegenLanguage(
codegenLanguage: requestCodeLanguage,
onChanged: (CodegenLanguage? value) {
ref.read(codegenLanguageStateProvider.notifier).state = value!;
},
);
}
}

View File

@ -0,0 +1,125 @@
import 'package:apidash/codegen/kotlin/pkg_okhttp.dart';
import 'package:apidash/models/request_model.dart';
import 'package:test/test.dart';
import 'package:apidash/consts.dart';
void main() {
group('KotlinOkHttpCodeGen', () {
final kotlinOkHttpCodeGen = KotlinOkHttpCodeGen();
test('getCode returns valid code for GET request', () {
const requestModel = RequestModel(
url: 'https://jsonplaceholder.typicode.com/todos/1',
method: HTTPVerb.get,
id: '',
);
const expectedCode = """import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
import java.util.concurrent.TimeUnit
val client = OkHttpClient()
val request = Request.Builder()
.url("https://jsonplaceholder.typicode.com/todos/1")
.build()
val response = client.newCall(request).execute()
println(response.body!!.string())
""";
expect(kotlinOkHttpCodeGen.getCode(requestModel), expectedCode);
});
test('getCode returns valid code for POST request', () {
const requestModel = RequestModel(
url: 'https://jsonplaceholder.typicode.com/posts',
method: HTTPVerb.post,
requestBody: '{"title": "foo","body": "bar","userId": 1}',
requestBodyContentType: ContentType.json,
id: '1',
);
const expectedCode = """import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
import java.util.concurrent.TimeUnit
val client = OkHttpClient()
val mediaType = "application/json".toMediaType()
val body = "{\"title\": \"foo\",\"body\": \"bar\",\"userId\": 1}".toRequestBody(mediaType)
val request = Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts")
.post(body)
.build()
val response = client.newCall(request).execute()
println(response.body!!.string())
""";
expect(kotlinOkHttpCodeGen.getCode(requestModel), expectedCode);
});
test('getCode returns valid code for DELETE request', () {
const requestModel = RequestModel(
url: 'https://jsonplaceholder.typicode.com/posts/1',
method: HTTPVerb.delete,
requestBody: '{"title": "foo","body": "bar","userId": 1}',
requestBodyContentType: ContentType.json,
id: '1',
);
const expectedCode = """import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
import java.util.concurrent.TimeUnit
val client = OkHttpClient()
val mediaType = "application/json".toMediaType()
val body = "{\"title\": \"foo\",\"body\": \"bar\",\"userId\": 1}".toRequestBody(mediaType)
val request = Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.method("DELETE", body)
.build()
val response = client.newCall(request).execute()
println(response.body!!.string())
""";
expect(kotlinOkHttpCodeGen.getCode(requestModel), expectedCode);
});
test('getCode returns valid code for HEAD request', () {
const requestModel = RequestModel(
url: 'https://jsonplaceholder.typicode.com/posts/1',
method: HTTPVerb.head,
id: '1',
);
const expectedCode = """import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
import java.util.concurrent.TimeUnit
val client = OkHttpClient()
val request = Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.head()
.build()
val response = client.newCall(request).execute()
println(response.body!!.string())
""";
expect(kotlinOkHttpCodeGen.getCode(requestModel), expectedCode);
});
});
}

View File

@ -1,30 +0,0 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:apidash/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}

View File

@ -1,3 +1,4 @@
import 'package:apidash/screens/home_page/editor_pane/details_card/code_pane.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:apidash/widgets/codegen_previewer.dart';