[file_selector] Migrate to null safety (#3631)

Migrates the app-facing package to null safety. Includes replacing Mockito with a custom fake/mock.

Fixes an issue where the example didn't handle dialogs being canceled, which was highlighted by the NNBD migration. (Previously, they would cause null assertions at runtime, which wasn't noticed during development. NNBD for the win!)

Fixes flutter/flutter#75235
diff --git a/packages/file_selector/file_selector/CHANGELOG.md b/packages/file_selector/file_selector/CHANGELOG.md
index fe01ffe..64ac595 100644
--- a/packages/file_selector/file_selector/CHANGELOG.md
+++ b/packages/file_selector/file_selector/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.8.0
+
+Migrate to null safety.
+
 ## 0.7.0+2
 
 * Update the example app: remove the deprecated `RaisedButton` and `FlatButton` widgets.
diff --git a/packages/file_selector/file_selector/example/lib/get_directory_page.dart b/packages/file_selector/file_selector/example/lib/get_directory_page.dart
index 6463fb5..cf4cde9 100644
--- a/packages/file_selector/file_selector/example/lib/get_directory_page.dart
+++ b/packages/file_selector/file_selector/example/lib/get_directory_page.dart
@@ -5,9 +5,13 @@
 class GetDirectoryPage extends StatelessWidget {
   void _getDirectoryPath(BuildContext context) async {
     final String confirmButtonText = 'Choose';
-    final String directoryPath = await getDirectoryPath(
+    final String? directoryPath = await getDirectoryPath(
       confirmButtonText: confirmButtonText,
     );
+    if (directoryPath == null) {
+      // Operation was canceled by the user.
+      return;
+    }
     await showDialog(
       context: context,
       builder: (context) => TextDisplay(directoryPath),
diff --git a/packages/file_selector/file_selector/example/lib/open_image_page.dart b/packages/file_selector/file_selector/example/lib/open_image_page.dart
index 593a1d6..986bfe7 100644
--- a/packages/file_selector/file_selector/example/lib/open_image_page.dart
+++ b/packages/file_selector/file_selector/example/lib/open_image_page.dart
@@ -11,6 +11,10 @@
       extensions: ['jpg', 'png'],
     );
     final List<XFile> files = await openFiles(acceptedTypeGroups: [typeGroup]);
+    if (files.isEmpty) {
+      // Operation was canceled by the user.
+      return;
+    }
     final XFile file = files[0];
     final String fileName = file.name;
     final String filePath = file.path;
diff --git a/packages/file_selector/file_selector/example/lib/open_multiple_images_page.dart b/packages/file_selector/file_selector/example/lib/open_multiple_images_page.dart
index 58b59cd..c6f73f5 100644
--- a/packages/file_selector/file_selector/example/lib/open_multiple_images_page.dart
+++ b/packages/file_selector/file_selector/example/lib/open_multiple_images_page.dart
@@ -18,6 +18,10 @@
       jpgsTypeGroup,
       pngTypeGroup,
     ]);
+    if (files.isEmpty) {
+      // Operation was canceled by the user.
+      return;
+    }
     await showDialog(
       context: context,
       builder: (context) => MultipleImagesDisplay(files),
diff --git a/packages/file_selector/file_selector/example/lib/open_text_page.dart b/packages/file_selector/file_selector/example/lib/open_text_page.dart
index 299d0e2..74d79dd 100644
--- a/packages/file_selector/file_selector/example/lib/open_text_page.dart
+++ b/packages/file_selector/file_selector/example/lib/open_text_page.dart
@@ -8,7 +8,11 @@
       label: 'text',
       extensions: ['txt', 'json'],
     );
-    final XFile file = await openFile(acceptedTypeGroups: [typeGroup]);
+    final XFile? file = await openFile(acceptedTypeGroups: [typeGroup]);
+    if (file == null) {
+      // Operation was canceled by the user.
+      return;
+    }
     final String fileName = file.name;
     final String fileContent = await file.readAsString();
 
diff --git a/packages/file_selector/file_selector/example/lib/save_text_page.dart b/packages/file_selector/file_selector/example/lib/save_text_page.dart
index 4740866..82046c3 100644
--- a/packages/file_selector/file_selector/example/lib/save_text_page.dart
+++ b/packages/file_selector/file_selector/example/lib/save_text_page.dart
@@ -8,7 +8,11 @@
   final TextEditingController _contentController = TextEditingController();
 
   void _saveFile() async {
-    final String path = await getSavePath();
+    String? path = await getSavePath();
+    if (path == null) {
+      // Operation was canceled by the user.
+      return;
+    }
     final String text = _contentController.text;
     final String fileName = _nameController.text;
     final Uint8List fileData = Uint8List.fromList(text.codeUnits);
diff --git a/packages/file_selector/file_selector/example/pubspec.yaml b/packages/file_selector/file_selector/example/pubspec.yaml
index 3af2a67..580237c 100644
--- a/packages/file_selector/file_selector/example/pubspec.yaml
+++ b/packages/file_selector/file_selector/example/pubspec.yaml
@@ -1,24 +1,12 @@
 name: example
 description: A new Flutter project.
 
-# The following line prevents the package from being accidentally published to
-# pub.dev using `pub publish`. This is preferred for private packages.
 publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 
-# The following defines the version and build number for your application.
-# A version number is three numbers separated by dots, like 1.2.43
-# followed by an optional build number separated by a +.
-# Both the version and the builder number may be overridden in flutter
-# build by specifying --build-name and --build-number, respectively.
-# In Android, build-name is used as versionName while build-number used as versionCode.
-# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
-# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
-# Read more about iOS versioning at
-# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 version: 1.0.0+1
 
 environment:
-  sdk: ">=2.7.0 <3.0.0"
+  sdk: ">=2.12.0-259.9.beta <3.0.0"
 
 dependencies:
   flutter:
@@ -32,52 +20,9 @@
     # the parent directory to use the current plugin's version.
     path: ../
 
-  # The following adds the Cupertino Icons font to your application.
-  # Use with the CupertinoIcons class for iOS style icons.
-  cupertino_icons: ^0.1.3
-
 dev_dependencies:
   flutter_test:
     sdk: flutter
 
-# For information on the generic Dart part of this file, see the
-# following page: https://dart.dev/tools/pub/pubspec
-
-# The following section is specific to Flutter.
 flutter:
-
-  # The following line ensures that the Material Icons font is
-  # included with your application, so that you can use the icons in
-  # the material Icons class.
   uses-material-design: true
-
-  # To add assets to your application, add an assets section, like this:
-  # assets:
-  #   - images/a_dot_burr.jpeg
-  #   - images/a_dot_ham.jpeg
-
-  # An image asset can refer to one or more resolution-specific "variants", see
-  # https://flutter.dev/assets-and-images/#resolution-aware.
-
-  # For details regarding adding assets from package dependencies, see
-  # https://flutter.dev/assets-and-images/#from-packages
-
-  # To add custom fonts to your application, add a fonts section here,
-  # in this "flutter" section. Each entry in this list should have a
-  # "family" key with the font family name, and a "fonts" key with a
-  # list giving the asset and other descriptors for the font. For
-  # example:
-  # fonts:
-  #   - family: Schyler
-  #     fonts:
-  #       - asset: fonts/Schyler-Regular.ttf
-  #       - asset: fonts/Schyler-Italic.ttf
-  #         style: italic
-  #   - family: Trajan Pro
-  #     fonts:
-  #       - asset: fonts/TrajanPro.ttf
-  #       - asset: fonts/TrajanPro_Bold.ttf
-  #         weight: 700
-  #
-  # For details regarding fonts from package dependencies,
-  # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/packages/file_selector/file_selector/lib/file_selector.dart b/packages/file_selector/file_selector/lib/file_selector.dart
index 080eac4..cdb2bf9 100644
--- a/packages/file_selector/file_selector/lib/file_selector.dart
+++ b/packages/file_selector/file_selector/lib/file_selector.dart
@@ -10,10 +10,10 @@
     show XFile, XTypeGroup;
 
 /// Open file dialog for loading files and return a file path
-Future<XFile> openFile({
-  List<XTypeGroup> acceptedTypeGroups,
-  String initialDirectory,
-  String confirmButtonText,
+Future<XFile?> openFile({
+  List<XTypeGroup> acceptedTypeGroups = const <XTypeGroup>[],
+  String? initialDirectory,
+  String? confirmButtonText,
 }) {
   return FileSelectorPlatform.instance.openFile(
       acceptedTypeGroups: acceptedTypeGroups,
@@ -23,9 +23,9 @@
 
 /// Open file dialog for loading files and return a list of file paths
 Future<List<XFile>> openFiles({
-  List<XTypeGroup> acceptedTypeGroups,
-  String initialDirectory,
-  String confirmButtonText,
+  List<XTypeGroup> acceptedTypeGroups = const <XTypeGroup>[],
+  String? initialDirectory,
+  String? confirmButtonText,
 }) {
   return FileSelectorPlatform.instance.openFiles(
       acceptedTypeGroups: acceptedTypeGroups,
@@ -34,11 +34,11 @@
 }
 
 /// Saves File to user's file system
-Future<String> getSavePath({
-  List<XTypeGroup> acceptedTypeGroups,
-  String initialDirectory,
-  String suggestedName,
-  String confirmButtonText,
+Future<String?> getSavePath({
+  List<XTypeGroup> acceptedTypeGroups = const <XTypeGroup>[],
+  String? initialDirectory,
+  String? suggestedName,
+  String? confirmButtonText,
 }) async {
   return FileSelectorPlatform.instance.getSavePath(
       acceptedTypeGroups: acceptedTypeGroups,
@@ -48,9 +48,9 @@
 }
 
 /// Gets a directory path from a user's file system
-Future<String> getDirectoryPath({
-  String initialDirectory,
-  String confirmButtonText,
+Future<String?> getDirectoryPath({
+  String? initialDirectory,
+  String? confirmButtonText,
 }) async {
   return FileSelectorPlatform.instance.getDirectoryPath(
       initialDirectory: initialDirectory, confirmButtonText: confirmButtonText);
diff --git a/packages/file_selector/file_selector/pubspec.yaml b/packages/file_selector/file_selector/pubspec.yaml
index a55b7f4..34b459c 100644
--- a/packages/file_selector/file_selector/pubspec.yaml
+++ b/packages/file_selector/file_selector/pubspec.yaml
@@ -1,21 +1,20 @@
 name: file_selector
 description: Flutter plugin for opening and saving files.
 homepage: https://github.com/flutter/plugins/tree/master/packages/file_selector/file_selector
-version: 0.7.0+2
+version: 0.8.0
 
 dependencies:
   flutter:
     sdk: flutter
-  file_selector_platform_interface: ^1.0.0
+  file_selector_platform_interface: ^2.0.0
 
 dev_dependencies:
   flutter_test:
     sdk: flutter
-  test: ^1.3.0
-  mockito: ^4.1.1
-  plugin_platform_interface: ^1.0.0
-  pedantic: ^1.8.0
+  test: ^1.16.3
+  plugin_platform_interface: ">=1.0.0 <3.0.0"
+  pedantic: ^1.10.0
 
 environment:
-  sdk: ">=2.1.0 <3.0.0"
-  flutter: ">=1.12.13+hotfix.5"
+  sdk: ">=2.12.0-259.9.beta <3.0.0"
+  flutter: ">=1.20.0"
diff --git a/packages/file_selector/file_selector/test/file_selector_test.dart b/packages/file_selector/file_selector/test/file_selector_test.dart
index 15756cc..b16f234 100644
--- a/packages/file_selector/file_selector/test/file_selector_test.dart
+++ b/packages/file_selector/file_selector/test/file_selector_test.dart
@@ -3,13 +3,13 @@
 // found in the LICENSE file.
 
 import 'package:flutter_test/flutter_test.dart';
-import 'package:mockito/mockito.dart';
 import 'package:plugin_platform_interface/plugin_platform_interface.dart';
 import 'package:file_selector/file_selector.dart';
 import 'package:file_selector_platform_interface/file_selector_platform_interface.dart';
+import 'package:test/fake.dart';
 
 void main() {
-  MockFileSelector mock;
+  late FakeFileSelector fakePlatformImplementation;
   final initialDirectory = '/home/flutteruser';
   final confirmButtonText = 'Use this profile picture';
   final suggestedName = 'suggested_name';
@@ -25,19 +25,20 @@
   ];
 
   setUp(() {
-    mock = MockFileSelector();
-    FileSelectorPlatform.instance = mock;
+    fakePlatformImplementation = FakeFileSelector();
+    FileSelectorPlatform.instance = fakePlatformImplementation;
   });
 
   group('openFile', () {
     final expectedFile = XFile('path');
 
     test('works', () async {
-      when(mock.openFile(
-        initialDirectory: initialDirectory,
-        confirmButtonText: confirmButtonText,
-        acceptedTypeGroups: acceptedTypeGroups,
-      )).thenAnswer((_) => Future.value(expectedFile));
+      fakePlatformImplementation
+        ..setExpectations(
+            initialDirectory: initialDirectory,
+            confirmButtonText: confirmButtonText,
+            acceptedTypeGroups: acceptedTypeGroups)
+        ..setFileResponse(<XFile>[expectedFile]);
 
       final file = await openFile(
         initialDirectory: initialDirectory,
@@ -49,7 +50,7 @@
     });
 
     test('works with no arguments', () async {
-      when(mock.openFile()).thenAnswer((_) => Future.value(expectedFile));
+      fakePlatformImplementation.setFileResponse(<XFile>[expectedFile]);
 
       final file = await openFile();
 
@@ -57,24 +58,27 @@
     });
 
     test('sets the initial directory', () async {
-      when(mock.openFile(initialDirectory: initialDirectory))
-          .thenAnswer((_) => Future.value(expectedFile));
+      fakePlatformImplementation
+        ..setExpectations(initialDirectory: initialDirectory)
+        ..setFileResponse(<XFile>[expectedFile]);
 
       final file = await openFile(initialDirectory: initialDirectory);
       expect(file, expectedFile);
     });
 
     test('sets the button confirmation label', () async {
-      when(mock.openFile(confirmButtonText: confirmButtonText))
-          .thenAnswer((_) => Future.value(expectedFile));
+      fakePlatformImplementation
+        ..setExpectations(confirmButtonText: confirmButtonText)
+        ..setFileResponse(<XFile>[expectedFile]);
 
       final file = await openFile(confirmButtonText: confirmButtonText);
       expect(file, expectedFile);
     });
 
     test('sets the accepted type groups', () async {
-      when(mock.openFile(acceptedTypeGroups: acceptedTypeGroups))
-          .thenAnswer((_) => Future.value(expectedFile));
+      fakePlatformImplementation
+        ..setExpectations(acceptedTypeGroups: acceptedTypeGroups)
+        ..setFileResponse(<XFile>[expectedFile]);
 
       final file = await openFile(acceptedTypeGroups: acceptedTypeGroups);
       expect(file, expectedFile);
@@ -85,11 +89,12 @@
     final expectedFiles = [XFile('path')];
 
     test('works', () async {
-      when(mock.openFiles(
-        initialDirectory: initialDirectory,
-        confirmButtonText: confirmButtonText,
-        acceptedTypeGroups: acceptedTypeGroups,
-      )).thenAnswer((_) => Future.value(expectedFiles));
+      fakePlatformImplementation
+        ..setExpectations(
+            initialDirectory: initialDirectory,
+            confirmButtonText: confirmButtonText,
+            acceptedTypeGroups: acceptedTypeGroups)
+        ..setFileResponse(expectedFiles);
 
       final file = await openFiles(
         initialDirectory: initialDirectory,
@@ -101,7 +106,7 @@
     });
 
     test('works with no arguments', () async {
-      when(mock.openFiles()).thenAnswer((_) => Future.value(expectedFiles));
+      fakePlatformImplementation.setFileResponse(expectedFiles);
 
       final files = await openFiles();
 
@@ -109,24 +114,27 @@
     });
 
     test('sets the initial directory', () async {
-      when(mock.openFiles(initialDirectory: initialDirectory))
-          .thenAnswer((_) => Future.value(expectedFiles));
+      fakePlatformImplementation
+        ..setExpectations(initialDirectory: initialDirectory)
+        ..setFileResponse(expectedFiles);
 
       final files = await openFiles(initialDirectory: initialDirectory);
       expect(files, expectedFiles);
     });
 
     test('sets the button confirmation label', () async {
-      when(mock.openFiles(confirmButtonText: confirmButtonText))
-          .thenAnswer((_) => Future.value(expectedFiles));
+      fakePlatformImplementation
+        ..setExpectations(confirmButtonText: confirmButtonText)
+        ..setFileResponse(expectedFiles);
 
       final files = await openFiles(confirmButtonText: confirmButtonText);
       expect(files, expectedFiles);
     });
 
     test('sets the accepted type groups', () async {
-      when(mock.openFiles(acceptedTypeGroups: acceptedTypeGroups))
-          .thenAnswer((_) => Future.value(expectedFiles));
+      fakePlatformImplementation
+        ..setExpectations(acceptedTypeGroups: acceptedTypeGroups)
+        ..setFileResponse(expectedFiles);
 
       final files = await openFiles(acceptedTypeGroups: acceptedTypeGroups);
       expect(files, expectedFiles);
@@ -137,12 +145,13 @@
     final expectedSavePath = '/example/path';
 
     test('works', () async {
-      when(mock.getSavePath(
-        initialDirectory: initialDirectory,
-        confirmButtonText: confirmButtonText,
-        acceptedTypeGroups: acceptedTypeGroups,
-        suggestedName: suggestedName,
-      )).thenAnswer((_) => Future.value(expectedSavePath));
+      fakePlatformImplementation
+        ..setExpectations(
+            initialDirectory: initialDirectory,
+            confirmButtonText: confirmButtonText,
+            acceptedTypeGroups: acceptedTypeGroups,
+            suggestedName: suggestedName)
+        ..setPathResponse(expectedSavePath);
 
       final savePath = await getSavePath(
         initialDirectory: initialDirectory,
@@ -155,32 +164,34 @@
     });
 
     test('works with no arguments', () async {
-      when(mock.getSavePath())
-          .thenAnswer((_) => Future.value(expectedSavePath));
+      fakePlatformImplementation.setPathResponse(expectedSavePath);
 
       final savePath = await getSavePath();
       expect(savePath, expectedSavePath);
     });
 
     test('sets the initial directory', () async {
-      when(mock.getSavePath(initialDirectory: initialDirectory))
-          .thenAnswer((_) => Future.value(expectedSavePath));
+      fakePlatformImplementation
+        ..setExpectations(initialDirectory: initialDirectory)
+        ..setPathResponse(expectedSavePath);
 
       final savePath = await getSavePath(initialDirectory: initialDirectory);
       expect(savePath, expectedSavePath);
     });
 
     test('sets the button confirmation label', () async {
-      when(mock.getSavePath(confirmButtonText: confirmButtonText))
-          .thenAnswer((_) => Future.value(expectedSavePath));
+      fakePlatformImplementation
+        ..setExpectations(confirmButtonText: confirmButtonText)
+        ..setPathResponse(expectedSavePath);
 
       final savePath = await getSavePath(confirmButtonText: confirmButtonText);
       expect(savePath, expectedSavePath);
     });
 
     test('sets the accepted type groups', () async {
-      when(mock.getSavePath(acceptedTypeGroups: acceptedTypeGroups))
-          .thenAnswer((_) => Future.value(expectedSavePath));
+      fakePlatformImplementation
+        ..setExpectations(acceptedTypeGroups: acceptedTypeGroups)
+        ..setPathResponse(expectedSavePath);
 
       final savePath =
           await getSavePath(acceptedTypeGroups: acceptedTypeGroups);
@@ -188,8 +199,9 @@
     });
 
     test('sets the suggested name', () async {
-      when(mock.getSavePath(suggestedName: suggestedName))
-          .thenAnswer((_) => Future.value(expectedSavePath));
+      fakePlatformImplementation
+        ..setExpectations(suggestedName: suggestedName)
+        ..setPathResponse(expectedSavePath);
 
       final savePath = await getSavePath(suggestedName: suggestedName);
       expect(savePath, expectedSavePath);
@@ -200,10 +212,11 @@
     final expectedDirectoryPath = '/example/path';
 
     test('works', () async {
-      when(mock.getDirectoryPath(
-        initialDirectory: initialDirectory,
-        confirmButtonText: confirmButtonText,
-      )).thenAnswer((_) => Future.value(expectedDirectoryPath));
+      fakePlatformImplementation
+        ..setExpectations(
+            initialDirectory: initialDirectory,
+            confirmButtonText: confirmButtonText)
+        ..setPathResponse(expectedDirectoryPath);
 
       final directoryPath = await getDirectoryPath(
         initialDirectory: initialDirectory,
@@ -214,16 +227,16 @@
     });
 
     test('works with no arguments', () async {
-      when(mock.getDirectoryPath())
-          .thenAnswer((_) => Future.value(expectedDirectoryPath));
+      fakePlatformImplementation.setPathResponse(expectedDirectoryPath);
 
       final directoryPath = await getDirectoryPath();
       expect(directoryPath, expectedDirectoryPath);
     });
 
     test('sets the initial directory', () async {
-      when(mock.getDirectoryPath(initialDirectory: initialDirectory))
-          .thenAnswer((_) => Future.value(expectedDirectoryPath));
+      fakePlatformImplementation
+        ..setExpectations(initialDirectory: initialDirectory)
+        ..setPathResponse(expectedDirectoryPath);
 
       final directoryPath =
           await getDirectoryPath(initialDirectory: initialDirectory);
@@ -231,8 +244,9 @@
     });
 
     test('sets the button confirmation label', () async {
-      when(mock.getDirectoryPath(confirmButtonText: confirmButtonText))
-          .thenAnswer((_) => Future.value(expectedDirectoryPath));
+      fakePlatformImplementation
+        ..setExpectations(confirmButtonText: confirmButtonText)
+        ..setPathResponse(expectedDirectoryPath);
 
       final directoryPath =
           await getDirectoryPath(confirmButtonText: confirmButtonText);
@@ -241,6 +255,83 @@
   });
 }
 
-class MockFileSelector extends Mock
+class FakeFileSelector extends Fake
     with MockPlatformInterfaceMixin
-    implements FileSelectorPlatform {}
+    implements FileSelectorPlatform {
+  // Expectations.
+  List<XTypeGroup>? acceptedTypeGroups = const <XTypeGroup>[];
+  String? initialDirectory;
+  String? confirmButtonText;
+  String? suggestedName;
+  // Return values.
+  List<XFile>? files;
+  String? path;
+
+  void setExpectations({
+    List<XTypeGroup> acceptedTypeGroups = const <XTypeGroup>[],
+    String? initialDirectory,
+    String? suggestedName,
+    String? confirmButtonText,
+  }) {
+    this.acceptedTypeGroups = acceptedTypeGroups;
+    this.initialDirectory = initialDirectory;
+    this.suggestedName = suggestedName;
+    this.confirmButtonText = confirmButtonText;
+  }
+
+  void setFileResponse(List<XFile> files) {
+    this.files = files;
+  }
+
+  void setPathResponse(String path) {
+    this.path = path;
+  }
+
+  @override
+  Future<XFile?> openFile({
+    List<XTypeGroup>? acceptedTypeGroups,
+    String? initialDirectory,
+    String? confirmButtonText,
+  }) async {
+    expect(acceptedTypeGroups, this.acceptedTypeGroups);
+    expect(initialDirectory, this.initialDirectory);
+    expect(suggestedName, this.suggestedName);
+    return files?[0];
+  }
+
+  @override
+  Future<List<XFile>> openFiles({
+    List<XTypeGroup>? acceptedTypeGroups,
+    String? initialDirectory,
+    String? confirmButtonText,
+  }) async {
+    expect(acceptedTypeGroups, this.acceptedTypeGroups);
+    expect(initialDirectory, this.initialDirectory);
+    expect(suggestedName, this.suggestedName);
+    return files!;
+  }
+
+  @override
+  Future<String?> getSavePath({
+    List<XTypeGroup>? acceptedTypeGroups,
+    String? initialDirectory,
+    String? suggestedName,
+    String? confirmButtonText,
+  }) async {
+    expect(acceptedTypeGroups, this.acceptedTypeGroups);
+    expect(initialDirectory, this.initialDirectory);
+    expect(suggestedName, this.suggestedName);
+    expect(confirmButtonText, this.confirmButtonText);
+    return path;
+  }
+
+  @override
+  Future<String?> getDirectoryPath({
+    String? initialDirectory,
+    String? confirmButtonText,
+  }) async {
+    expect(initialDirectory, this.initialDirectory);
+    expect(confirmButtonText, this.confirmButtonText);
+    return path;
+  }
+}