| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library test_utils; | |
| 6 | |
| 7 import 'dart:convert'; | |
| 8 | |
| 9 import 'package:http/http.dart' as http; | |
| 10 import 'package:http_parser/http_parser.dart'; | |
| 11 import 'package:unittest/unittest.dart'; | |
| 12 | |
| 13 /// A dummy URL for constructing requests that won't be sent. | |
| 14 Uri get dummyUrl => Uri.parse('http://dartlang.org/'); | |
| 15 | |
| 16 /// Removes eight spaces of leading indentation from a multiline string. | |
| 17 /// | |
| 18 /// Note that this is very sensitive to how the literals are styled. They should | |
| 19 /// be: | |
| 20 /// ''' | |
| 21 /// Text starts on own line. Lines up with subsequent lines. | |
| 22 /// Lines are indented exactly 8 characters from the left margin. | |
| 23 /// Close is on the same line.''' | |
| 24 /// | |
| 25 /// This does nothing if text is only a single line. | |
| 26 // TODO(nweiz): Make this auto-detect the indentation level from the first | |
| 27 // non-whitespace line. | |
| 28 String cleanUpLiteral(String text) { | |
| 29 var lines = text.split('\n'); | |
| 30 if (lines.length <= 1) return text; | |
| 31 | |
| 32 for (var j = 0; j < lines.length; j++) { | |
| 33 if (lines[j].length > 8) { | |
| 34 lines[j] = lines[j].substring(8, lines[j].length); | |
| 35 } else { | |
| 36 lines[j] = ''; | |
| 37 } | |
| 38 } | |
| 39 | |
| 40 return lines.join('\n'); | |
| 41 } | |
| 42 | |
| 43 /// A matcher that matches JSON that parses to a value that matches the inner | |
| 44 /// matcher. | |
| 45 Matcher parse(matcher) => new _Parse(matcher); | |
| 46 | |
| 47 class _Parse extends Matcher { | |
| 48 final Matcher _matcher; | |
| 49 | |
| 50 _Parse(this._matcher); | |
| 51 | |
| 52 bool matches(item, Map matchState) { | |
| 53 if (item is! String) return false; | |
| 54 | |
| 55 var parsed; | |
| 56 try { | |
| 57 parsed = JSON.decode(item); | |
| 58 } catch (e) { | |
| 59 return false; | |
| 60 } | |
| 61 | |
| 62 return _matcher.matches(parsed, matchState); | |
| 63 } | |
| 64 | |
| 65 Description describe(Description description) { | |
| 66 return description.add('parses to a value that ') | |
| 67 .addDescriptionOf(_matcher); | |
| 68 } | |
| 69 } | |
| 70 | |
| 71 /// A matcher that validates the body of a multipart request after finalization. | |
| 72 /// The string "{{boundary}}" in [pattern] will be replaced by the boundary | |
| 73 /// string for the request, and LF newlines will be replaced with CRLF. | |
| 74 /// Indentation will be normalized. | |
| 75 Matcher bodyMatches(String pattern) => new _BodyMatches(pattern); | |
| 76 | |
| 77 class _BodyMatches extends Matcher { | |
| 78 final String _pattern; | |
| 79 | |
| 80 _BodyMatches(this._pattern); | |
| 81 | |
| 82 bool matches(item, Map matchState) { | |
| 83 if (item is! http.MultipartRequest) return false; | |
| 84 | |
| 85 var future = item.finalize().toBytes().then((bodyBytes) { | |
| 86 var body = UTF8.decode(bodyBytes); | |
| 87 var contentType = new MediaType.parse(item.headers['content-type']); | |
| 88 var boundary = contentType.parameters['boundary']; | |
| 89 var expected = cleanUpLiteral(_pattern) | |
| 90 .replaceAll("\n", "\r\n") | |
| 91 .replaceAll("{{boundary}}", boundary); | |
| 92 | |
| 93 expect(body, equals(expected)); | |
| 94 expect(item.contentLength, equals(bodyBytes.length)); | |
| 95 }); | |
| 96 | |
| 97 return completes.matches(future, matchState); | |
| 98 } | |
| 99 | |
| 100 Description describe(Description description) { | |
| 101 return description.add('has a body that matches "$_pattern"'); | |
| 102 } | |
| 103 } | |
| 104 | |
| 105 /// A matcher that matches a [http.ClientException] with the given [message]. | |
| 106 /// | |
| 107 /// [message] can be a String or a [Matcher]. | |
| 108 Matcher isClientException(message) => predicate((error) { | |
| 109 expect(error, new isInstanceOf<http.ClientException>()); | |
| 110 expect(error.message, message); | |
| 111 return true; | |
| 112 }); | |
| 113 | |
| 114 /// A matcher that matches function or future that throws a | |
| 115 /// [http.ClientException] with the given [message]. | |
| 116 /// | |
| 117 /// [message] can be a String or a [Matcher]. | |
| 118 Matcher throwsClientException(message) => throwsA(isClientException(message)); | |
| OLD | NEW |