1- import 'dart:html ' ;
1+ import 'dart:js_interop ' ;
22
33import 'package:ngdart/angular.dart' ;
44import 'package:test/test.dart' ;
5+ import 'package:web/web.dart' ;
56
67/// Matches textual content of an element including children.
78Matcher hasTextContent (String expected) => _HasTextContent (expected);
89
10+ /// Matches DOMTokenList.
11+ Matcher hasDomTokenList (List <String > expected) => _HasDomTokenList (expected);
12+
13+ /// Matches textual content of an element including children.
14+ Matcher hasInnerHtml (String expected) => _HasInnerHtml (expected);
15+
916final throwsNoProviderError = throwsA (_isNoProviderError);
1017final _isNoProviderError = const TypeMatcher <NoProviderError >();
1118
@@ -15,7 +22,8 @@ class _HasTextContent extends Matcher {
1522 const _HasTextContent (this .expectedText);
1623
1724 @override
18- bool matches (Object ? item, void _) => _elementText (item) == expectedText;
25+ bool matches (Object ? item, void _) =>
26+ _elementText (item as JSAny ? ) == expectedText;
1927
2028 @override
2129 Description describe (Description description) =>
@@ -29,33 +37,100 @@ class _HasTextContent extends Matcher {
2937 void __,
3038 ) {
3139 mismatchDescription.add ('Text content of element: '
32- '\' ${_elementText (item )}\' ' );
40+ '\' ${_elementText (item as JSAny ? )}\' ' );
3341 return mismatchDescription;
3442 }
3543}
3644
37- String ? _elementText (Object ? n) {
38- if (n is Iterable ) {
39- return n.map (_elementText).join ('' );
40- } else if (n is Node ) {
41- if (n is Comment ) {
45+ String ? _elementText (JSAny ? node) {
46+ if (node.isA <NodeList >()) {
47+ return < String ? > [
48+ for (var i = 0 ; i < (node as NodeList ).length; i++ )
49+ _elementText (node.item (i))
50+ ].join ('' );
51+ }
52+
53+ if (node.isA <Node >()) {
54+ if (node.isA <Comment >()) {
4255 return '' ;
4356 }
4457
45- if (n is ContentElement ) {
46- return _elementText (n.getDistributedNodes ());
58+ if (node.isA <Element >() && (node as Element ).shadowRoot != null ) {
59+ return _elementText (node.shadowRoot! .childNodes);
60+ }
61+
62+ if ((node as Node ).childNodes.length != 0 ) {
63+ return _elementText (node.childNodes);
4764 }
4865
49- if (n is Element && n.shadowRoot != null ) {
50- return _elementText (n.shadowRoot! .nodes);
66+ return node.textContent;
67+ }
68+
69+ return null ;
70+ }
71+
72+ class _HasDomTokenList extends Matcher {
73+ final List <String ?> expectedTokens;
74+
75+ const _HasDomTokenList (this .expectedTokens);
76+
77+ @override
78+ bool matches (Object ? item, void _) {
79+ final tokens = item as DOMTokenList ;
80+
81+ if (tokens.length != expectedTokens.length) {
82+ return false ;
5183 }
5284
53- if (n.nodes.isNotEmpty) {
54- return _elementText (n.nodes);
85+ for (var i = 0 ; i < expectedTokens.length; i++ ) {
86+ if (tokens.item (i) != expectedTokens[i]) {
87+ return false ;
88+ }
5589 }
5690
57- return n.text;
58- } else {
59- return '$n ' ;
91+ return true ;
92+ }
93+
94+ @override
95+ Description describe (Description description) {
96+ return description.add (expectedTokens.join (',' ));
97+ }
98+
99+ @override
100+ Description describeMismatch (
101+ item,
102+ Description mismatchDescription,
103+ void _,
104+ void __,
105+ ) {
106+ mismatchDescription.add ('DOMTokenList: \' $item }\' ' );
107+ return mismatchDescription;
108+ }
109+ }
110+
111+ class _HasInnerHtml extends Matcher {
112+ final String expectedHtml;
113+
114+ const _HasInnerHtml (this .expectedHtml);
115+
116+ @override
117+ bool matches (Object ? item, void _) {
118+ return ((item as Element ).innerHTML as JSString ).toDart == expectedHtml;
119+ }
120+
121+ @override
122+ Description describe (Description description) =>
123+ description.add (expectedHtml);
124+
125+ @override
126+ Description describeMismatch (
127+ item,
128+ Description mismatchDescription,
129+ void _,
130+ void __,
131+ ) {
132+ mismatchDescription.add ('Inner HTML of element: '
133+ '\' ${_elementText (item as Element )}\' ' );
134+ return mismatchDescription;
60135 }
61136}
0 commit comments