Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Improve DomHelper tests.
  • Loading branch information
tugorez committed Jan 12, 2021
commit dc715250798198de43d1a0d5b58b25f34496c34c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class FileSelectorWeb extends FileSelectorPlatform {
bool multiple = false,
}) async {
final accept = acceptedTypesToString(acceptedTypeGroups);
final List<File> files = await _domHelper.getFilesFromInput(
final List<File> files = await _domHelper.getFiles(
accept: accept,
multiple: multiple,
);
Expand Down
35 changes: 16 additions & 19 deletions packages/file_selector/file_selector_web/lib/src/dom_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,44 @@ import 'package:flutter/services.dart';

/// Class to manipulate the DOM with the intention of reading files from it.
class DomHelper {
final FileUploadInputElement _input;
final _container = Element.tag('file-selector');

/// Default constructor, initializes _input (an html <input /> element).
DomHelper({@visibleForTesting FileUploadInputElement input})
: _input = input ?? FileUploadInputElement() {
DomHelper() {
final body = querySelector('body');
final container = Element.tag('file-selector');
body.children.add(container);
container.children.add(_input);
body.children.add(_container);
}

/// Sets the <input /> attributes and waits for a file to be selected.
Future<List<File>> getFilesFromInput({
Future<List<File>> getFiles({
String accept = '',
bool multiple = false,
@visibleForTesting FileUploadInputElement input,
}) {
final Completer<List<File>> _completer = Completer();
StreamSubscription<Event> onChangeSubscription;
StreamSubscription<Event> onErrorSubscription;

_input
..accept = accept
..multiple = multiple;
_container.children.add(
(input ?? FileUploadInputElement())
..accept = accept
..multiple = multiple,
);

onChangeSubscription = _input.onChange.listen((_) {
final List<File> files = _input.files;
onChangeSubscription.cancel();
input.onChange.first.then((_) {
final List<File> files = input.files;
input.remove();
_completer.complete(files);
});

onErrorSubscription = _input.onError.listen((event) {
input.onError.first.then((event) {
final ErrorEvent error = event;
final platformException = PlatformException(
code: error.type,
message: error.message,
);
onErrorSubscription.cancel();
input.remove();
_completer.completeError(platformException);
});

_input.click();
input.click();

return _completer.future;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,93 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:file_selector_web/src/dom_helper.dart';
import 'package:pedantic/pedantic.dart';
import 'package:mockito/mockito.dart';

void main() {
group('FileSelectorWeb', () {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
DomHelper domHelper;
MockInput mockInput;
FileUploadInputElement input;

FileList FileListItems(List<File> files) {
final dataTransfer = DataTransfer();
files.forEach(dataTransfer.items.add);
return dataTransfer.files;
}

void setFilesAndTriggerChange(List<File> files) {
input.files = FileListItems(files);
input.dispatchEvent(Event('change'));
}

setUp(() {
mockInput = MockInput();
domHelper = DomHelper(input: mockInput);
domHelper = DomHelper();
input = FileUploadInputElement();
});

testWidgets('creates a container and an <input /> element', (_) async {
domHelper = DomHelper();
final container = querySelector('file-selector');
final input = querySelector('file-selector input');
group('getFiles', () {
final mockFile1 = File([], 'file1.txt');
final mockFile2 = File([], 'file2.txt');

expect(container, isNotNull);
expect(input, isNotNull);
});
testWidgets('works', (_) async {
final futureFile = domHelper.getFiles(input: input);

setFilesAndTriggerChange([mockFile1, mockFile2]);

final files = await futureFile;

expect(files.length, 2);

expect(files[0], mockFile1);
expect(files[1], mockFile2);
});

testWidgets('works multiple times', (_) async {
Future<List<File>> futureFiles;
List<File> files;

group('getFilesFromInput', () {
testWidgets('sets the <input /> attributes and click it', (_) async {
final accept = '.png,.jpg,.txt,.json';
// It should work the first time
futureFiles = domHelper.getFiles(input: input);
setFilesAndTriggerChange([mockFile1]);

files = await futureFiles;

expect(files.length, 1);
expect(files.first, mockFile1);

// The same input should work more than once
futureFiles = domHelper.getFiles(input: input);
setFilesAndTriggerChange([mockFile2]);

files = await futureFiles;

expect(files.length, 1);
expect(files.first, mockFile2);
});

testWidgets('sets the <input /> attributes and clicks it', (_) async {
final accept = '.jpg,.png';
final multiple = true;
bool wasClicked = false;

unawaited(input.onClick.first.then((_) => wasClicked = true));

final futureFile = domHelper.getFiles(
accept: accept,
multiple: multiple,
input: input,
);

unawaited(
domHelper.getFilesFromInput(accept: accept, multiple: multiple));
expect(input.matchesWithAncestors('body'), true);
expect(input.accept, accept);
expect(input.multiple, multiple);
expect(wasClicked, true);

expect(mockInput.accept, accept);
expect(mockInput.multiple, multiple);
verify(mockInput.click());
setFilesAndTriggerChange([]);
await futureFile;

// It should be already removed from the DOM after the file is resolved.
expect(input.parent, isNull);
});
});
});
}

class MockInput extends Mock implements FileUploadInputElement {}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void main() {
webWildCards: ['image/*'],
);

when(mockDomHelper.getFilesFromInput(
when(mockDomHelper.getFiles(
accept: '.jpg,.jpeg,image/png,image/*',
multiple: false,
)).thenAnswer((_) async => [mockFile]);
Expand All @@ -43,7 +43,7 @@ void main() {

expect(file.name, mockFile.name);
expect(await file.length(), 4);
expect(await file.readAsString(), 'random content');
expect(await file.readAsString(), '1001');
expect(await file.lastModified(), isNotNull);
});
});
Expand All @@ -58,7 +58,7 @@ void main() {
extensions: ['.txt'],
);

when(mockDomHelper.getFilesFromInput(
when(mockDomHelper.getFiles(
accept: '.txt',
multiple: true,
)).thenAnswer((_) async => [mockFile1, mockFile2]);
Expand Down