Skip to content

Commit

Permalink
fix #856: picking .app files on macOS
Browse files Browse the repository at this point in the history
.app files on macOS are actually directories. But, they are treated as
files by the file picker and therefore can only be selected via
'FilePicker.platform.pickFiles()'. When picking .app files,
'createPlatformFile()' tries to get the size of the .app file which
throws an exception because directories don't have an inherent size.
  • Loading branch information
philenius committed Oct 20, 2021
1 parent ba4d365 commit 8fc9bd3
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 16 deletions.
3 changes: 2 additions & 1 deletion lib/src/platform_file.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class PlatformFile {
/// File content as stream
final Stream<List<int>>? readStream;

/// The file size in bytes.
/// The file size in bytes. Defaults to `0` if the file size could not be
/// determined.
final int size;

/// File extension for this file.
Expand Down
2 changes: 1 addition & 1 deletion lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Future<PlatformFile> createPlatformFile(
name: basename(file.path),
path: file.path,
readStream: readStream,
size: await file.length(),
size: file.existsSync() ? file.lengthSync() : 0,
);

Future<String?> runExecutableWithArguments(
Expand Down
30 changes: 18 additions & 12 deletions test/common.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
import 'dart:io';

setUpTestFiles(
String imageTestFile,
String pdfTestFile,
String yamlTestFile,
String appTestFilePath,
String imageTestFilePath,
String pdfTestFilePath,
String yamlTestFilePath,
) {
// .app files on macOS are actually directories but they are treated as files
Directory(appTestFilePath).createSync();

File(
'./test/test_files/franz-michael-schneeberger-unsplash.jpg',
).copySync(imageTestFile);
).copySync(imageTestFilePath);
File(
'./test/test_files/test.pdf',
).copySync(pdfTestFile);
).copySync(pdfTestFilePath);
File(
'./test/test_files/test.yml',
).copySync(yamlTestFile);
).copySync(yamlTestFilePath);
}

tearDownTestFiles(
String imageTestFile,
String pdfTestFile,
String yamlTestFile,
String appTestFilePath,
String imageTestFilePath,
String pdfTestFilePath,
String yamlTestFilePath,
) {
File(imageTestFile).deleteSync();
File(pdfTestFile).deleteSync();
File(yamlTestFile).deleteSync();
Directory(appTestFilePath).deleteSync();
File(imageTestFilePath).deleteSync();
File(pdfTestFilePath).deleteSync();
File(yamlTestFilePath).deleteSync();
}
41 changes: 39 additions & 2 deletions test/file_picker_utils_test.dart
Original file line number Diff line number Diff line change
@@ -1,23 +1,60 @@
@TestOn('linux || mac-os')

import 'dart:io';
import 'package:file_picker/src/utils.dart';
import 'package:flutter_test/flutter_test.dart';

import 'common.dart';

void main() {
final appTestFilePath = '/tmp/test_utils.app';
final imageTestFile = '/tmp/test_utils.jpg';
final pdfTestFile = '/tmp/test_utils.pdf';
final yamlTestFile = '/tmp/test_utils.yml';

setUpAll(
() => setUpTestFiles(imageTestFile, pdfTestFile, yamlTestFile),
() => setUpTestFiles(
appTestFilePath, imageTestFile, pdfTestFile, yamlTestFile),
);

tearDownAll(
() => tearDownTestFiles(imageTestFile, pdfTestFile, yamlTestFile),
() => tearDownTestFiles(
appTestFilePath, imageTestFile, pdfTestFile, yamlTestFile),
);

group('createPlatformFile()', () {
test('should return an instance of PlatformFile', () async {
final imageFile = File(imageTestFile);
final bytes = imageFile.readAsBytesSync();
final readStream = imageFile.openRead();

final platformFile =
await createPlatformFile(imageFile, bytes, readStream);

expect(platformFile.bytes, equals(bytes));
expect(platformFile.name, equals('test_utils.jpg'));
expect(platformFile.readStream, equals(readStream));
expect(platformFile.size, equals(bytes.length));
});

test(
'should not throw an exception when picking .app files on macOS (.app files on macOS are actually directories but they are treated as files, similar to .exe files on Windows)',
() async {
final appFile = File(appTestFilePath);

final platformFile = await createPlatformFile(appFile, null, null);

expect(platformFile.bytes, equals(null));
expect(platformFile.name, equals('test_utils.app'));
expect(platformFile.readStream, equals(null));
expect(
platformFile.size,
equals(0),
reason: 'Expect size to be 0 because .app files are directories.',
);
});
});

group('filePathsToPlatformFiles()', () {
test('should transform a list of file paths into a list of PlatformFiles',
() async {
Expand Down

0 comments on commit 8fc9bd3

Please sign in to comment.