diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart index c7da9753..c8c3ca68 100644 --- a/lib/providers/collection_providers.dart +++ b/lib/providers/collection_providers.dart @@ -378,7 +378,9 @@ class CollectionStateNotifier }; unsave(); }, onError: (e) { - print('Stream error: $e'); + if (!completer.isCompleted) { + completer.complete((null, null, 'StreamError: $e')); + } }); final (response, duration, errorMessage) = await completer.future; diff --git a/packages/better_networking/test/services/request_types/rest_test.dart b/packages/better_networking/test/services/request_types/rest_test.dart index e506ba41..ae12a32b 100644 --- a/packages/better_networking/test/services/request_types/rest_test.dart +++ b/packages/better_networking/test/services/request_types/rest_test.dart @@ -192,17 +192,27 @@ void main() { ); }); }); + group('Testing overrideContentType functionality', () { + test('overrideContentType is true', () async { + final request = prepareHttpRequest( + url: Uri.parse('https://www.example.com'), + method: 'POST', + body: 'Hello', + headers: {'content-type': 'application/json'}, + overrideContentType: true, + ); + expect(request.headers['content-type'], 'application/json'); + }); - //TODO: Needs to be Discussed - // test('prepareHttpRequest: check overrideContentType ', () async { - // final request = prepareHttpRequest( - // url: Uri.parse('https://www.example.com'), - // method: 'POST', - // body: '{"key":"value"}', - // headers: {'content-type': 'application/json'}, - // overrideContentType: true, - // ); - // print(request.headers); - // expect(request.headers['content-type'], isNot('application/json')); - // }); + test('overrideContentType is false', () async { + final request = prepareHttpRequest( + url: Uri.parse('https://www.example.com'), + method: 'POST', + body: 'Hello', + headers: {'content-type': 'application/json'}, + overrideContentType: false, + ); + expect(request.headers['content-type'], isNot('application/json')); + }); + }); } diff --git a/test/providers/collection_providers_test.dart b/test/providers/collection_providers_test.dart index 097b71f0..ef4beef5 100644 --- a/test/providers/collection_providers_test.dart +++ b/test/providers/collection_providers_test.dart @@ -1,5 +1,7 @@ +import 'dart:io'; import 'package:apidash/screens/home_page/editor_pane/details_card/request_pane/request_body.dart'; import 'package:apidash/widgets/editor.dart'; +import 'package:apidash/widgets/response_body.dart'; import 'package:apidash_core/apidash_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -51,4 +53,69 @@ void main() async { // Verify that the Snackbar is shown expect(find.text('Switched to POST method'), findsOneWidget); }, skip: true); + + testWidgets('SSE Output is rendered correctly in UI', + (WidgetTester tester) async { + HttpOverrides.global = null; //enable networking in flutter_test + + final container = createContainer(); + final notifier = container.read(collectionStateNotifierProvider.notifier); + + const model = HttpRequestModel( + url: 'https://sse-demo.netlify.app/sse', + method: HTTPVerb.get, + ); + + notifier.addRequestModel(model, name: 'sseM'); + final id = notifier.state!.entries.last.key; + + //runAsync to enable user-code awaiting + await tester.runAsync(() async { + await notifier.sendRequest(); + await Future.delayed(const Duration(seconds: 3)); + }); + + final rm = notifier.getRequestModel(id)!; + cancelHttpRequest(rm.id); + + final sseOutput = (rm.httpResponseModel?.sseOutput ?? []) + .map((e) => e.trim()) + .where((e) => e.isNotEmpty) + .toList(); + + expect(sseOutput, isNotEmpty, reason: 'No SSE Output found'); + + // Render the widget + await tester.pumpWidget( + ProviderScope( + // ignore: deprecated_member_use + parent: container, + child: MaterialApp( + home: Scaffold( + body: ResponseBody(selectedRequestModel: rm), + ), + ), + ), + ); + await tester.pumpAndSettle(); + + final textWidgets = tester.widgetList(find.byType(Text)); + final matchingTextCount = textWidgets + .where((text) => + text.data != null && + text.data!.startsWith('data') && + sseOutput.contains(text.data!.trim())) + .length; + + expect( + matchingTextCount, + sseOutput.length, + reason: 'UI does not match all SSE output lines', + ); + + // Waits for all provider actions to complete before exit + await tester.runAsync(() async { + await Future.delayed(const Duration(seconds: 2)); + }); + }); }