Merge branch 'foss42:main' into main

This commit is contained in:
Aashutosh soni
2024-03-04 22:29:33 +05:30
committed by GitHub
15 changed files with 223 additions and 51 deletions

View File

@ -16,4 +16,3 @@ _We encourage you to add relevant test cases._
- [ ] Yes - [ ] Yes
- [ ] No, and this is why: _please replace this line with details on why tests have not been included_ - [ ] No, and this is why: _please replace this line with details on why tests have not been included_
- [ ] I need help with writing tests

View File

@ -137,6 +137,7 @@ Here is the complete list of mimetypes that can be directly previewed in API Das
| File Type | Mimetype | Extension | Comment | | File Type | Mimetype | Extension | Comment |
| --------- | -------------------------- | ----------------- | -------- | | --------- | -------------------------- | ----------------- | -------- |
| PDF | `application/pdf` | `.pdf` | | | PDF | `application/pdf` | `.pdf` | |
| CSV | `text/csv` | `.csv` | Can be improved |
| Image | `image/apng` | `.apng` | Animated | | Image | `image/apng` | `.apng` | Animated |
| Image | `image/avif` | `.avif` | | | Image | `image/avif` | `.avif` | |
| Image | `image/bmp` | `.bmp` | | | Image | `image/bmp` | `.bmp` | |
@ -177,14 +178,14 @@ Here is the complete list of mimetypes that are syntax highlighted in API Dash:
| ------------------ | --------- | ------------------------------------------------------------------------------------------------------------------ | | ------------------ | --------- | ------------------------------------------------------------------------------------------------------------------ |
| `application/json` | `.json` | Other mimetypes like `application/geo+json`, `application/vcard+json` that are based on `json` are also supported. | | `application/json` | `.json` | Other mimetypes like `application/geo+json`, `application/vcard+json` that are based on `json` are also supported. |
| `application/xml` | `.xml` | Other mimetypes like `application/xhtml+xml`, `application/vcard+xml` that are based on `xml` are also supported. | | `application/xml` | `.xml` | Other mimetypes like `application/xhtml+xml`, `application/vcard+xml` that are based on `xml` are also supported. |
| `text/xml` | `.xml` | | | `text/xml` | `.xml` | |
| `application/yaml` | `.yaml` | Others - `application/x-yaml` or `application/x-yml` | | `application/yaml` | `.yaml` | Others - `application/x-yaml` or `application/x-yml` |
| `text/yaml` | `.yaml` | Others - `text/yml` | | `text/yaml` | `.yaml` | Others - `text/yml` |
| `application/sql` | `.sql` | | | `application/sql` | `.sql` | |
| `text/css` | `.css` | | | `text/css` | `.css` | |
| `text/html` | `.html` | Only syntax highlighting, no web preview. | | `text/html` | `.html` | Only syntax highlighting, no web preview. |
| `text/javascript` | `.js` | | | `text/javascript` | `.js` | |
| `text/markdown` | `.md` | | | `text/markdown` | `.md` | |
## What's new in v0.3.0? ## What's new in v0.3.0?

View File

@ -3,8 +3,9 @@ include: package:flutter_lints/flutter.yaml
analyzer: analyzer:
errors: errors:
invalid_annotation_target: ignore invalid_annotation_target: ignore
enable-experiment: exclude:
- records - "**/*.freezed.dart"
- "**/*.g.dart"
linter: linter:
rules: rules:

View File

@ -379,6 +379,7 @@ const Map<String, Map<String, List<ResponseBodyView>>>
kSubTypeDefaultViewOptions: kRawBodyViewOptions, kSubTypeDefaultViewOptions: kRawBodyViewOptions,
kSubTypeCss: kCodeRawBodyViewOptions, kSubTypeCss: kCodeRawBodyViewOptions,
kSubTypeHtml: kCodeRawBodyViewOptions, kSubTypeHtml: kCodeRawBodyViewOptions,
kSubTypeCsv: kPreviewRawBodyViewOptions,
kSubTypeJavascript: kCodeRawBodyViewOptions, kSubTypeJavascript: kCodeRawBodyViewOptions,
kSubTypeMarkdown: kCodeRawBodyViewOptions, kSubTypeMarkdown: kCodeRawBodyViewOptions,
kSubTypeTextXml: kCodeRawBodyViewOptions, kSubTypeTextXml: kCodeRawBodyViewOptions,
@ -496,6 +497,9 @@ const kAudioError =
const kRaiseIssue = const kRaiseIssue =
"\nPlease raise an issue in API Dash GitHub repo so that we can resolve it."; "\nPlease raise an issue in API Dash GitHub repo so that we can resolve it.";
const kCsvError =
"There seems to be an issue rendering this CSV. Please raise an issue in API Dash GitHub repo so that we can resolve it.";
const kHintTextUrlCard = "Enter API endpoint like api.foss42.com/country/codes"; const kHintTextUrlCard = "Enter API endpoint like api.foss42.com/country/codes";
const kLabelPlusNew = "+ New"; const kLabelPlusNew = "+ New";
const kLabelSend = "Send"; const kLabelSend = "Send";

View File

@ -2,6 +2,7 @@ Map<String, String> headers = {
"Accept": "Specifies the media types that are acceptable for the response.", "Accept": "Specifies the media types that are acceptable for the response.",
"Accept-Encoding": "Accept-Encoding":
"Indicates the encoding methods the client can understand.", "Indicates the encoding methods the client can understand.",
"Accept-Charset": "Specifies the character sets that are acceptable.",
"Access-Control-Allow-Headers": "Access-Control-Allow-Headers":
"Specifies a list of HTTP headers that can be used in an actual request after a preflight request including the Access-Control-Request-Headers header is made.", "Specifies a list of HTTP headers that can be used in an actual request after a preflight request including the Access-Control-Request-Headers header is made.",
"Access-Control-Allow-Methods": "Access-Control-Allow-Methods":
@ -41,11 +42,16 @@ Map<String, String> headers = {
"Cross-Origin-Resource-Policy": "Cross-Origin-Resource-Policy":
"Controls how cross-origin requests for resources are handled.", "Controls how cross-origin requests for resources are handled.",
"Date": "Indicates the date and time at which the message was sent.", "Date": "Indicates the date and time at which the message was sent.",
"Device-Memory":
"Indicates the approximate amount of device memory in gigabytes.",
"DNT": "DNT":
"Informs websites whether the user's preference is to opt out of online tracking.", "Informs websites whether the user's preference is to opt out of online tracking.",
"Expect": "Indicates certain expectations that need to be met by the server.", "Expect": "Indicates certain expectations that need to be met by the server.",
"Expires": "Expires":
"Contains the date/time after which the response is considered expired", "Contains the date/time after which the response is considered expired",
"Forwarded":
"Contains information from the client-facing side of proxy servers that is altered or lost when a proxy is involved in the path of the request.",
"From": "Contains an Internet email address for a human user who controls the requesting user agent.",
"Host": "Specifies the domain name of the server and the port number.", "Host": "Specifies the domain name of the server and the port number.",
"If-Match": "If-Match":
"Used for conditional requests, allows the server to respond based on certain conditions.", "Used for conditional requests, allows the server to respond based on certain conditions.",
@ -57,9 +63,15 @@ Map<String, String> headers = {
"Used in conjunction with the Range header to conditionally request a partial resource.", "Used in conjunction with the Range header to conditionally request a partial resource.",
"If-Unmodified-Since": "If-Unmodified-Since":
"Used for conditional requests, allows the server to respond based on certain conditions.", "Used for conditional requests, allows the server to respond based on certain conditions.",
"Keep-Alive":
"Used to allow the connection to be reused for further requests.",
"Location": "Location":
"Indicates the URL a client should redirect to for further interaction.", "Indicates the URL a client should redirect to for further interaction.",
"Max-Forwards":
"Indicates the remaining number of times a request can be forwarded by proxies.",
"Origin": "Specifies the origin of a cross-origin request.", "Origin": "Specifies the origin of a cross-origin request.",
"Proxy-Authorization":
"Contains credentials for authenticating a client with a proxy server.",
"Range": "Range":
"Used to request only part of a resource, typically in the context of downloading large files.", "Used to request only part of a resource, typically in the context of downloading large files.",
"Referer": "Referer":
@ -68,10 +80,14 @@ Map<String, String> headers = {
"Specifies how much information the browser should include in the Referer header when navigating to other pages.", "Specifies how much information the browser should include in the Referer header when navigating to other pages.",
"Retry-After": "Retry-After":
"Informs the client how long it should wait before making another request after a server has responded with a rate-limiting status code.", "Informs the client how long it should wait before making another request after a server has responded with a rate-limiting status code.",
"Save-Data":
"Indicates the client's preference for reduced data usage.",
"Server": "Indicates the software used by the origin server.", "Server": "Indicates the software used by the origin server.",
"Strict-Transport-Security": "Strict-Transport-Security":
"Instructs the browser to always use HTTPS for the given domain.", "Instructs the browser to always use HTTPS for the given domain.",
"TE": "Specifies the transfer encodings that are acceptable to the client.", "TE": "Specifies the transfer encodings that are acceptable to the client.",
"Upgrade-Insecure-Requests":
"Instructs the browser to prefer secure connections when available.",
"User-Agent": "User-Agent":
"Identifies the client software and version making the request.", "Identifies the client software and version making the request.",
"Via": "Via":

View File

@ -0,0 +1,53 @@
import 'package:flutter/material.dart';
import 'package:csv/csv.dart';
import 'error_message.dart';
import '../consts.dart';
class CsvPreviewer extends StatelessWidget {
const CsvPreviewer({super.key, required this.body});
final String body;
@override
Widget build(BuildContext context) {
try {
final List<List<dynamic>> csvData =
const CsvToListConverter().convert(body, eol: '\n');
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: csvData[0]
.map(
(item) => DataColumn(
label: Text(
item.toString(),
),
),
)
.toList(),
rows: csvData
.skip(1)
.map(
(csvrow) => DataRow(
cells: csvrow
.map(
(csvItem) => DataCell(
Text(
csvItem.toString(),
),
),
)
.toList(),
),
)
.toList(),
),
),
);
} catch (e) {
return const ErrorMessage(message: kCsvError);
}
}
}

View File

@ -1,6 +1,6 @@
import 'package:apidash/consts.dart';
import 'package:apidash/utils/header_utils.dart'; import 'package:apidash/utils/header_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:apidash/consts.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart';
class HeaderField extends StatefulWidget { class HeaderField extends StatefulWidget {
@ -41,6 +41,7 @@ class _HeaderFieldState extends State<HeaderField> {
@override @override
void didUpdateWidget(HeaderField oldWidget) { void didUpdateWidget(HeaderField oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.initialValue != widget.initialValue) { if (oldWidget.initialValue != widget.initialValue) {
controller.text = widget.initialValue ?? ""; controller.text = widget.initialValue ?? "";
controller.selection = controller.selection =
@ -54,8 +55,8 @@ class _HeaderFieldState extends State<HeaderField> {
return TypeAheadField( return TypeAheadField(
key: Key(widget.keyId), key: Key(widget.keyId),
hideOnEmpty: true, hideOnEmpty: true,
minCharsForSuggestions: 1, controller: controller,
onSuggestionSelected: (value) { onSelected: (value) {
setState(() { setState(() {
controller.text = value; controller.text = value;
}); });
@ -68,19 +69,17 @@ class _HeaderFieldState extends State<HeaderField> {
); );
}, },
suggestionsCallback: headerSuggestionCallback, suggestionsCallback: headerSuggestionCallback,
suggestionsBoxDecoration: suggestionBoxDecorations(context), decorationBuilder: (context, child) =>
textFieldConfiguration: TextFieldConfiguration( suggestionBoxDecorations(context, child, colorScheme),
constraints: const BoxConstraints(maxHeight: 400),
builder: (context, controller, focusNode) => TextField(
onChanged: widget.onChanged, onChanged: widget.onChanged,
controller: controller, controller: controller,
style: kCodeStyle.copyWith( focusNode: focusNode,
color: colorScheme.onSurface, style: kCodeStyle.copyWith(color: colorScheme.onSurface),
),
decoration: InputDecoration( decoration: InputDecoration(
hintStyle: kCodeStyle.copyWith( hintStyle: kCodeStyle.copyWith(
color: colorScheme.outline.withOpacity( color: colorScheme.outline.withOpacity(kHintOpacity)),
kHintOpacity,
),
),
hintText: widget.hintText, hintText: widget.hintText,
focusedBorder: UnderlineInputBorder( focusedBorder: UnderlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
@ -99,22 +98,26 @@ class _HeaderFieldState extends State<HeaderField> {
); );
} }
SuggestionsBoxDecoration suggestionBoxDecorations(BuildContext context) { Theme suggestionBoxDecorations(
return SuggestionsBoxDecoration( BuildContext context, Widget child, ColorScheme colorScheme) {
elevation: 4, return Theme(
constraints: const BoxConstraints(maxHeight: 400), data: ThemeData(colorScheme: colorScheme),
shape: RoundedRectangleBorder( child: Material(
side: BorderSide( elevation: 4,
color: Theme.of(context).dividerColor, shape: RoundedRectangleBorder(
width: 1.2, side: BorderSide(color: Theme.of(context).dividerColor, width: 1.2),
borderRadius: const BorderRadius.vertical(bottom: Radius.circular(8)),
), ),
borderRadius: const BorderRadius.vertical(bottom: Radius.circular(8)), clipBehavior: Clip.hardEdge,
child: child,
), ),
clipBehavior: Clip.hardEdge,
); );
} }
Future<List<String>> headerSuggestionCallback(String pattern) async { Future<List<String>?> headerSuggestionCallback(String pattern) async {
if (pattern.isEmpty) {
return null;
}
return getHeaderSuggestions(pattern); return getHeaderSuggestions(pattern);
} }
} }

View File

@ -154,6 +154,7 @@ class _JsonPreviewerState extends State<JsonPreviewer> {
@override @override
void didUpdateWidget(JsonPreviewer oldWidget) { void didUpdateWidget(JsonPreviewer oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.code != widget.code) { if (oldWidget.code != widget.code) {
store.buildNodes(widget.code, areAllCollapsed: true); store.buildNodes(widget.code, areAllCollapsed: true);
store.expandAll(); store.expandAll();

View File

@ -7,6 +7,7 @@ import 'package:vector_graphics_compiler/vector_graphics_compiler.dart';
import 'error_message.dart'; import 'error_message.dart';
import 'uint8_audio_player.dart'; import 'uint8_audio_player.dart';
import 'json_previewer.dart'; import 'json_previewer.dart';
import 'csv_previewer.dart';
import '../consts.dart'; import '../consts.dart';
class Previewer extends StatefulWidget { class Previewer extends StatefulWidget {
@ -81,6 +82,9 @@ class _PreviewerState extends State<Previewer> {
}, },
); );
} }
if (widget.type == kTypeText && widget.subtype == kSubTypeCsv) {
return CsvPreviewer(body: widget.body);
}
if (widget.type == kTypeVideo) { if (widget.type == kTypeVideo) {
// TODO: Video Player // TODO: Video Player
} }

View File

@ -217,6 +217,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.3"
csv:
dependency: "direct main"
description:
name: csv
sha256: "63ed2871dd6471193dffc52c0e6c76fb86269c00244d244297abbb355c84a86e"
url: "https://pub.dev"
source: hosted
version: "5.1.1"
dart_style: dart_style:
dependency: "direct main" dependency: "direct main"
description: description:
@ -306,10 +314,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: flutter_keyboard_visibility name: flutter_keyboard_visibility
sha256: "4983655c26ab5b959252ee204c2fffa4afeb4413cd030455194ec0caa3b8e7cb" sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.4.1" version: "6.0.0"
flutter_keyboard_visibility_linux: flutter_keyboard_visibility_linux:
dependency: transitive dependency: transitive
description: description:
@ -407,10 +415,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_typeahead name: flutter_typeahead
sha256: b9942bd5b7611a6ec3f0730c477146cffa4cd4b051077983ba67ddfc9e7ee818 sha256: d64712c65db240b1057559b952398ebb6e498077baeebf9b0731dade62438a6d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.8.0" version: "5.2.0"
flutter_web_plugins: flutter_web_plugins:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -625,6 +633,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.0" version: "0.2.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
url: "https://pub.dev"
source: hosted
version: "10.0.0"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
url: "https://pub.dev"
source: hosted
version: "2.0.1"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
url: "https://pub.dev"
source: hosted
version: "2.0.1"
lints: lints:
dependency: transitive dependency: transitive
description: description:
@ -661,26 +693,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.16" version: "0.12.16+1"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.0" version: "0.8.0"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.10.0" version: "1.11.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@ -757,10 +789,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: path name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.8.3" version: "1.9.0"
path_parsing: path_parsing:
dependency: transitive dependency: transitive
description: description:
@ -853,10 +885,34 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: pointer_interceptor name: pointer_interceptor
sha256: adf7a637f97c077041d36801b43be08559fd4322d2127b3f20bb7be1b9eebc22 sha256: bd18321519718678d5fa98ad3a3359cbc7a31f018554eab80b73d08a7f0c165a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.9.3+7" version: "0.10.1"
pointer_interceptor_ios:
dependency: transitive
description:
name: pointer_interceptor_ios
sha256: "2e73c39452830adc4695757130676a39412a3b7f3c34e3f752791b5384770877"
url: "https://pub.dev"
source: hosted
version: "0.10.0+2"
pointer_interceptor_platform_interface:
dependency: transitive
description:
name: pointer_interceptor_platform_interface
sha256: "0597b0560e14354baeb23f8375cd612e8bd4841bf8306ecb71fcd0bb78552506"
url: "https://pub.dev"
source: hosted
version: "0.10.0+1"
pointer_interceptor_web:
dependency: transitive
description:
name: pointer_interceptor_web
sha256: "9386e064097fd16419e935c23f08f35b58e6aaec155dd39bd6a003b88f9c14b4"
url: "https://pub.dev"
source: hosted
version: "0.10.1+2"
pointycastle: pointycastle:
dependency: transitive dependency: transitive
description: description:

View File

@ -41,7 +41,7 @@ dependencies:
json_annotation: ^4.8.1 json_annotation: ^4.8.1
printing: ^5.11.1 printing: ^5.11.1
package_info_plus: ^4.1.0 package_info_plus: ^4.1.0
flutter_typeahead: ^4.8.0 flutter_typeahead: ^5.2.0
provider: ^6.0.5 provider: ^6.0.5
json_data_explorer: json_data_explorer:
git: git:
@ -54,6 +54,7 @@ dependencies:
code_builder: ^4.9.0 code_builder: ^4.9.0
dart_style: ^2.3.4 dart_style: ^2.3.4
json_text_field: ^1.1.0 json_text_field: ^1.1.0
csv: ^5.1.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@ -115,6 +115,7 @@ void main() {
String pattern = "x-"; String pattern = "x-";
List<String> expected = [ List<String> expected = [
"Access-Control-Max-Age", "Access-Control-Max-Age",
"Max-Forwards",
"X-Api-Key", "X-Api-Key",
"X-Content-Type-Options", "X-Content-Type-Options",
"X-CSRF-Token", "X-CSRF-Token",

View File

@ -1,3 +1,6 @@
// ignore_for_file: unused_import
// TODO: Added ignore to calculate code coverage
import 'package:apidash/main.dart'; import 'package:apidash/main.dart';
import 'package:apidash/app.dart'; import 'package:apidash/app.dart';
import 'package:apidash/common/utils.dart'; import 'package:apidash/common/utils.dart';

View File

@ -1,9 +1,16 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:apidash/widgets/intro_message.dart'; import 'package:apidash/widgets/intro_message.dart';
import 'package:package_info_plus/package_info_plus.dart';
void main() { void main() {
testWidgets('Testing Intro Message', (tester) async { testWidgets('Testing Intro Message', (tester) async {
PackageInfo.setMockInitialValues(
appName: 'API Dash',
packageName: 'dev.apidash.apidash',
version: '1.0.0',
buildNumber: '1',
buildSignature: 'buildSignature');
await tester.pumpWidget( await tester.pumpWidget(
const MaterialApp( const MaterialApp(
title: 'Intro Message', title: 'Intro Message',
@ -13,7 +20,7 @@ void main() {
), ),
); );
await tester.pumpAndSettle(); await tester.pump();
expect(find.text('Welcome to API Dash ⚡️'), findsOneWidget); expect(find.text('Welcome to API Dash ⚡️'), findsOneWidget);
expect(find.byType(RichText), findsAtLeastNWidgets(1)); expect(find.byType(RichText), findsAtLeastNWidgets(1));
@ -25,5 +32,5 @@ void main() {
expect(find.byIcon(Icons.star), findsOneWidget); expect(find.byIcon(Icons.star), findsOneWidget);
expect(find.text('Star on GitHub'), findsOneWidget); expect(find.text('Star on GitHub'), findsOneWidget);
await tester.tap(find.byIcon(Icons.star)); await tester.tap(find.byIcon(Icons.star));
}, skip: true); });
} }

View File

@ -231,4 +231,26 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text(kSvgError), findsOneWidget); expect(find.text(kSvgError), findsOneWidget);
}); });
testWidgets('Testing when type/subtype is text/csv', (tester) async {
String csvDataString =
'Id,Name,Age\n1,John Doe,40\n2,Dbestech,41\n3,Voldermort,71\n4,Joe Biden,80\n5,Ryo Hanamura,35';
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Previewer(
type: kTypeText,
subtype: kSubTypeCsv,
bytes: Uint8List.fromList([]),
body: csvDataString,
),
),
),
);
expect(find.byType(DataTable), findsOneWidget);
expect(find.text('John Doe'), findsOneWidget);
expect(find.text('41'), findsOneWidget);
});
} }