OLD | NEW |
| (Empty) |
1 /** | |
2 * This package contains matches to write tests for parsers. | |
3 * | |
4 * Examples: | |
5 * | |
6 * var json = new JsonParser(); | |
7 * | |
8 * // verifies that the input gets parsed and all input is consumed | |
9 * expect('{"a": 1}', accepts(new JsonParser())); | |
10 * | |
11 * // verifies that the input gets parsed to a dictionary and that all input
is consumed | |
12 * expect('{"a": 1}', parses(new JsonParser(), {'a': 1})); | |
13 */ | |
14 | |
15 library test_util; | |
16 | |
17 import 'package:matcher/matcher.dart'; | |
18 import 'package:petitparser/petitparser.dart' hide predicate; | |
19 | |
20 /** | |
21 * Returns a matcher that succeeds if the [parser] accepts the input. | |
22 */ | |
23 Matcher accept(Parser parser) { | |
24 return parse(parser, predicate((value) => true, 'input')); | |
25 } | |
26 | |
27 /** | |
28 * Returns a matcher that succeeds if the [parser] succeeds and accepts the prov
ided [matcher]. | |
29 */ | |
30 Matcher parse(Parser parser, matcher, [int position = -1]) { | |
31 return new _Parse(parser, wrapMatcher(matcher), position); | |
32 } | |
33 | |
34 class _Parse extends Matcher { | |
35 | |
36 final Parser parser; | |
37 final Matcher matcher; | |
38 final int position; | |
39 | |
40 _Parse(this.parser, this.matcher, this.position); | |
41 | |
42 @override | |
43 bool matches(item, Map matchState) { | |
44 Result result = parser.parse(item); | |
45 if (result.isFailure) { | |
46 addStateInfo(matchState, {'reason': 'failure', 'result': result}); | |
47 return false; | |
48 } | |
49 if (!matcher.matches(result.value, matchState)) { | |
50 addStateInfo(matchState, {'reason': 'matcher', 'result': result}); | |
51 return false; | |
52 } | |
53 if (position >= 0 && position != result.value) { | |
54 addStateInfo(matchState, {'reason': 'position', 'result': result}); | |
55 return false; | |
56 } | |
57 return true; | |
58 } | |
59 | |
60 @override | |
61 Description describe(Description description) { | |
62 return description.add('"$parser" accepts ').addDescriptionOf(matcher); | |
63 } | |
64 | |
65 @override | |
66 Description describeMismatch(item, Description description, Map matchState, bo
ol verbose) { | |
67 description.add('"$parser" produces "${matchState['result']}"'); | |
68 switch (matchState['reason']) { | |
69 case 'failure': | |
70 description.add(' which is not accepted'); | |
71 return description; | |
72 case 'matcher': | |
73 description.add(' which parse result '); | |
74 var subDescription = new StringDescription(); | |
75 matcher.describeMismatch(matchState['result'].value, subDescription, | |
76 matchState['state'], verbose); | |
77 if (subDescription.length > 0) { | |
78 description.add(subDescription.toString()); | |
79 } else { | |
80 description.add('doesn\'t match'); | |
81 matcher.describe(description); | |
82 } | |
83 return description; | |
84 case 'position': | |
85 description | |
86 .add(' that consumes input to ') | |
87 .add(matchState['result'].position.toString()) | |
88 .add(' instead of ') | |
89 .add(position.toString()); | |
90 return description; | |
91 } | |
92 throw new Exception('Internal matcher error'); | |
93 } | |
94 } | |
OLD | NEW |