145 lines
4.6 KiB
Dart
145 lines
4.6 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:open_filex/open_filex.dart';
|
|
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
|
|
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
|
import 'package:ikar/core/utils/download_history.dart';
|
|
import 'package:ikar/core/utils/file_download.dart';
|
|
import 'package:ikar/core/utils/media_cache.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
class _Paths extends PathProviderPlatform with MockPlatformInterfaceMixin {
|
|
_Paths(this.path);
|
|
final String path;
|
|
@override
|
|
Future<String?> getApplicationSupportPath() async => path;
|
|
}
|
|
|
|
class _RealHttpOverrides extends HttpOverrides {}
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
late Directory directory;
|
|
late PathProviderPlatform paths;
|
|
|
|
setUp(() {
|
|
directory = Directory.systemTemp.createTempSync('qlyra_file_download_');
|
|
paths = PathProviderPlatform.instance;
|
|
PathProviderPlatform.instance = _Paths(directory.path);
|
|
MediaCache.resetForTesting();
|
|
DownloadHistory.resetForTesting();
|
|
SharedPreferences.setMockInitialValues({});
|
|
});
|
|
tearDown(() {
|
|
MediaCache.resetForTesting();
|
|
DownloadHistory.resetForTesting();
|
|
PathProviderPlatform.instance = paths;
|
|
directory.deleteSync(recursive: true);
|
|
});
|
|
|
|
for (final name in [
|
|
'report.pdf',
|
|
'archive.zip',
|
|
'document.docx',
|
|
'data.bin',
|
|
'song.mp3',
|
|
'picture.png',
|
|
]) {
|
|
test(
|
|
'$name downloads on first tap and opens offline on second tap',
|
|
() async {
|
|
await HttpOverrides.runWithHttpOverrides(() async {
|
|
final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
|
|
addTearDown(() => server.close(force: true));
|
|
final bytes = List<int>.generate(2048, (i) => i % 256);
|
|
var requests = 0;
|
|
server.listen((request) async {
|
|
requests++;
|
|
request.response.contentLength = bytes.length;
|
|
request.response.add(bytes);
|
|
await request.response.close();
|
|
});
|
|
var resolves = 0;
|
|
var opens = 0;
|
|
var ready = 0;
|
|
final progress = <double>[];
|
|
Future<String?> resolve() async {
|
|
resolves++;
|
|
return 'http://127.0.0.1:${server.port}/file';
|
|
}
|
|
|
|
Future<OpenResult> open(String path) async {
|
|
opens++;
|
|
expect(await File(path).readAsBytes(), bytes);
|
|
return OpenResult(type: ResultType.done, message: 'done');
|
|
}
|
|
|
|
final first = await openCachedFile(
|
|
name,
|
|
resolve,
|
|
downloadOnlyIfMissing: true,
|
|
openFile: open,
|
|
onReady: () => ready++,
|
|
onProgress: progress.add,
|
|
download: DownloadMetadata(
|
|
cacheName: name,
|
|
name: name,
|
|
kind: downloadKindForName(name),
|
|
),
|
|
);
|
|
expect(first.ok, isTrue);
|
|
expect(first.downloaded, isTrue);
|
|
expect(opens, 0);
|
|
expect(ready, 1);
|
|
expect(progress.last, 1);
|
|
expect(DownloadHistory.records.value.single.name, name);
|
|
await server.close(force: true);
|
|
|
|
final second = await openCachedFile(
|
|
name,
|
|
resolve,
|
|
downloadOnlyIfMissing: true,
|
|
openFile: open,
|
|
);
|
|
expect(second.ok, isTrue);
|
|
expect(second.downloaded, isFalse);
|
|
expect(opens, 1);
|
|
expect(resolves, 1);
|
|
expect(requests, 1);
|
|
}, _RealHttpOverrides());
|
|
},
|
|
);
|
|
}
|
|
|
|
test('missing URL resets progress and permits retry', () async {
|
|
var ready = 0;
|
|
final result = await openCachedFile(
|
|
'missing.pdf',
|
|
() async => null,
|
|
downloadOnlyIfMissing: true,
|
|
onReady: () => ready++,
|
|
openFile: (_) async => throw StateError('must not open'),
|
|
);
|
|
expect(result.ok, isFalse);
|
|
expect(result.path, isNull);
|
|
expect(ready, 1);
|
|
expect(await MediaCache.existing('missing.pdf'), isNull);
|
|
});
|
|
|
|
test('no viewer keeps the downloaded document available', () async {
|
|
final file = await MediaCache.fileFor('report.pdf');
|
|
await file.writeAsBytes([1, 2, 3]);
|
|
final result = await openCachedFile(
|
|
'report.pdf',
|
|
() async => throw StateError('must not resolve'),
|
|
downloadOnlyIfMissing: true,
|
|
openFile: (_) async =>
|
|
OpenResult(type: ResultType.noAppToOpen, message: 'No viewer'),
|
|
);
|
|
expect(result.noAppToOpen, isTrue);
|
|
expect(result.path, file.path);
|
|
expect(await file.readAsBytes(), [1, 2, 3]);
|
|
});
|
|
}
|