blob: aa20ffb57bfa1323ea962d94160e4c6b529da1fc [file] [log] [blame]
library http_mock;
import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
class MockHttpHeaders implements HttpHeaders {
final Map<String, List<String>> _headers =
new HashMap<String, List<String>>();
DateTime get ifModifiedSince {
List<String> values = _headers[HttpHeaders.IF_MODIFIED_SINCE];
if (values != null) {
try {
return HttpDate.parse(values[0]);
} on Exception catch (e) {
return null;
}
}
return null;
}
void set ifModifiedSince(DateTime ifModifiedSince) {
// Format "ifModifiedSince" header with date in Greenwich Mean Time (GMT).
String formatted = HttpDate.format(ifModifiedSince.toUtc());
_set(HttpHeaders.IF_MODIFIED_SINCE, formatted);
}
ContentType contentType;
void set(String name, Object value) {
name = name.toLowerCase();
_headers.remove(name);
_addAll(name, value);
}
String value(String name) {
name = name.toLowerCase();
List<String> values = _headers[name];
if (values == null) return null;
if (values.length > 1) {
throw new HttpException("More than one value for header $name");
}
return values[0];
}
String toString() => '$runtimeType : $_headers';
// [name] must be a lower-case version of the name.
void _add(String name, value) {
if (name == HttpHeaders.IF_MODIFIED_SINCE) {
if (value is DateTime) {
ifModifiedSince = value;
} else if (value is String) {
_set(HttpHeaders.IF_MODIFIED_SINCE, value);
} else {
throw new HttpException("Unexpected type for header named $name");
}
} else {
_addValue(name, value);
}
}
void _addAll(String name, value) {
if (value is List) {
for (int i = 0; i < value.length; i++) {
_add(name, value[i]);
}
} else {
_add(name, value);
}
}
void _addValue(String name, Object value) {
List<String> values = _headers[name];
if (values == null) {
values = new List<String>();
_headers[name] = values;
}
if (value is DateTime) {
values.add(HttpDate.format(value));
} else {
values.add(value.toString());
}
}
void _set(String name, String value) {
assert(name == name.toLowerCase());
List<String> values = new List<String>();
_headers[name] = values;
values.add(value);
}
/*
* Implemented to remove editor warnings
*/
dynamic noSuchMethod(Invocation invocation) {
print([invocation.memberName, invocation.isGetter, invocation.isSetter, invocation.isMethod, invocation.isAccessor]);
return super.noSuchMethod(invocation);
}
}
class MockHttpRequest implements HttpRequest {
final Uri uri;
final MockHttpResponse response = new MockHttpResponse();
final HttpHeaders headers = new MockHttpHeaders();
final String method = 'GET';
final bool followRedirects;
MockHttpRequest(this.uri, {this.followRedirects: true,
DateTime ifModifiedSince}) {
if(ifModifiedSince != null) {
headers.ifModifiedSince = ifModifiedSince;
}
}
/*
* Implemented to remove editor warnings
*/
dynamic noSuchMethod(Invocation invocation) =>
super.noSuchMethod(invocation);
}
class MockHttpResponse implements HttpResponse {
final HttpHeaders headers = new MockHttpHeaders();
final Completer _completer = new Completer();
final List<int> _buffer = new List<int>();
String _reasonPhrase;
Future _doneFuture;
MockHttpResponse() {
_doneFuture = _completer.future
.whenComplete(() {
assert(!_isDone);
_isDone = true;
});
}
bool _isDone = false;
int statusCode = HttpStatus.OK;
String get reasonPhrase => _findReasonPhrase(statusCode);
void set reasonPhrase(String value) {
_reasonPhrase = value;
}
Future get done => _doneFuture;
Future close() {
_completer.complete();
return _doneFuture;
}
void add(List<int> data) {
_buffer.addAll(data);
}
void addError(error, [StackTrace stackTrace]) {
// doesn't seem to be hit...hmm...
}
Future redirect(Uri location, {int status: HttpStatus.MOVED_TEMPORARILY}) {
this.statusCode = status;
headers.set(HttpHeaders.LOCATION, location.toString());
return close();
}
void write(Object obj) {
var str = obj.toString();
add(UTF8.encode(str));
}
/*
* Implemented to remove editor warnings
*/
dynamic noSuchMethod(Invocation invocation) =>
super.noSuchMethod(invocation);
String get mockContent => UTF8.decode(_buffer);
bool get mockDone => _isDone;
// Copied from SDK http_impl.dart @ 845 on 2014-01-05
// TODO: file an SDK bug to expose this on HttpStatus in some way
String _findReasonPhrase(int statusCode) {
if (_reasonPhrase != null) {
return _reasonPhrase;
}
switch (statusCode) {
case HttpStatus.NOT_FOUND: return "Not Found";
default: return "Status $statusCode";
}
}
}