Skip to content

Instantly share code, notes, and snippets.

@j0nscalet
Created January 28, 2021 07:06
Show Gist options
  • Save j0nscalet/a82ecc8e86b5522439c92cb05c4a830e to your computer and use it in GitHub Desktop.
Save j0nscalet/a82ecc8e86b5522439c92cb05c4a830e to your computer and use it in GitHub Desktop.
Client to track upload progress
import 'dart:async';
import 'dart:io';
import 'package:http/io_client.dart';
import 'package:http/http.dart' hide Client;
import 'package:test/test.dart';
import 'package:uploader/services/client.dart';
import 'package:uploader/extensions/round_double_to_decimal_places.dart';
void main() async {
HttpClient inner;
Client client;
StreamController<Map<String, dynamic>> controller;
Request request;
MultipartRequest multipartRequest;
MultipartFile multipartFile;
setUp(() async {
controller = StreamController<Map<String, dynamic>>.broadcast(sync: true);
inner = HttpClient();
client = Client(inner, controller);
multipartRequest =
MultipartRequest('POST', Uri.parse('https://httpbin.org/post'));
multipartFile =
await MultipartFile.fromPath('file', 'test/fixtures/lisanto.jpg');
multipartRequest.files.add(multipartFile);
});
request = Request('POST', Uri.parse('https://httpbin.org/post'));
group('constructs', () {
test('inner http client is required', () {
expect(() => Client(null, null), throwsA(isA<AssertionError>()));
});
test('uploadProgressController stream must be a broadcast stream', () {
expect(
() => Client(HttpClient(), StreamController<Map<String, dynamic>>()),
throwsA(isA<AssertionError>()));
});
});
test('close', () {
var client = Client(HttpClient(), null);
client.close();
expect(client.inner, isNull);
});
test('send with an invalid URL', () async {
var request = Request('POST', Uri.parse('http://http.invalid'));
request.headers[HttpHeaders.contentTypeHeader] =
'application/json; charset=utf-8';
expect(client.send(request), throwsA(isA<SocketException>()));
});
test('send without tracking upload progress', () async {
client = Client(inner, null);
var response = await client.send(multipartRequest);
expect(response.statusCode, 200);
expect(response.request.followRedirects, multipartRequest.followRedirects);
expect(response.request.maxRedirects, multipartRequest.maxRedirects);
expect(response.request.contentLength, multipartRequest.contentLength);
expect(response.request.persistentConnection,
multipartRequest.persistentConnection);
}, timeout: Timeout(Duration(minutes: 10)));
test('send and track upload progress', () async {
var events = <Map<String, dynamic>>[];
client.uploadProgressStream.listen((event) {
events.add(event);
});
await client.send(multipartRequest);
expect(events.length, greaterThan(0));
expect(
events.every((e) =>
e.containsKey('status') &&
e.containsKey('url') &&
e.containsKey('progress') &&
e.containsKey('bytesUploaded') &&
e.containsKey('totalBytes') &&
e.containsKey('elapsedTime') &&
e.containsKey('averageSpeed')),
equals(true));
expect(events.first['status'], equals('uploading'));
expect(events.last['status'], equals("uploaded"));
expect(events.last['progress'], equals(100.0));
}, timeout: Timeout(Duration(minutes: 10)));
test('calculate elapsed time and average speed of upload', () async {
// ignore: omit_local_variable_types
double bytesReceived = 0.0;
double bytesUploaded;
client.uploadProgressStream.listen((event) {
bytesUploaded = event['bytesUploaded'];
print("[client] $event");
});
var server = await HttpServer.bind("127.0.0.1", 0);
server.listen((request) async {
request.listen((event) {
bytesReceived += (event.lengthInBytes / 1000);
var totalBytes = (request.contentLength / 1000);
var progress = ((bytesReceived / totalBytes) * 100.0);
print("[server] ${{
'progress': progress,
'bytesReceived': bytesReceived,
}}");
}, onDone: () async {
await request.response.close();
await server.close();
await expectLater(
bytesReceived.roundToPlaces(3), equals(bytesUploaded));
});
});
var request = MultipartRequest('POST',
Uri(scheme: "http", host: "127.0.0.1", port: server.port, path: "/"));
request.files.add(multipartFile);
await client.send(request);
}, timeout: Timeout(Duration(minutes: 10)));
test('sends a multipart request with correct content-type header', () async {
await client.send(multipartRequest);
expect(multipartRequest.headers['content-type'],
startsWith('multipart/form-data; boundary='));
});
test('detachSocket returns a socket from an IOStreamedResponse', () async {
var response = await client.send(request) as IOStreamedResponse;
var socket = await response.detachSocket();
expect(socket, isNotNull);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment