Skip to content

Commit 645b49b

Browse files
committed
Add unit tests for all image source matchers
1 parent 0bd3132 commit 645b49b

File tree

2 files changed

+112
-2
lines changed

2 files changed

+112
-2
lines changed

lib/image_render.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ typedef ImageSourceMatcher = bool Function(
1111
dom.Element element,
1212
);
1313

14-
ImageSourceMatcher base64UriMatcher() => (attributes, element) =>
14+
ImageSourceMatcher base64DataUriMatcher() => (attributes, element) =>
1515
_src(attributes) != null &&
1616
_src(attributes).startsWith("data:image") &&
1717
_src(attributes).contains("base64,");
@@ -159,7 +159,7 @@ ImageRender svgNetworkImageRender() => (context, attributes, element) {
159159
};
160160

161161
final Map<ImageSourceMatcher, ImageRender> defaultImageRenders = {
162-
base64UriMatcher(): base64ImageRender(),
162+
base64DataUriMatcher(): base64ImageRender(),
163163
assetUriMatcher(): assetImageRender(),
164164
networkSourceMatcher(extension: "svg"): svgNetworkImageRender(),
165165
networkSourceMatcher(): networkImageRender(),
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import 'package:flutter_html/image_render.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:html/dom.dart' as dom;
4+
5+
void main() {
6+
group("asset uri matcher", () {
7+
ImageSourceMatcher matcher = assetUriMatcher();
8+
test("matches a full asset: uri", () {
9+
expect(_match(matcher, 'asset:some/asset.png'), isTrue);
10+
});
11+
test("matches asset: schema without path", () {
12+
expect(_match(matcher, 'asset:'), isTrue);
13+
});
14+
test("doesn't match literal host 'asset'", () {
15+
expect(_match(matcher, 'asset/faulty.path'), isFalse);
16+
});
17+
test("doesn't match null", () {
18+
expect(_match(matcher, null), isFalse);
19+
});
20+
test("doesn't match empty", () {
21+
expect(_match(matcher, ''), isFalse);
22+
});
23+
});
24+
group("default network source matcher", () {
25+
ImageSourceMatcher matcher = networkSourceMatcher();
26+
test("matches a full http uri", () {
27+
expect(_match(matcher, 'http://legacy.http/uri.png'), isTrue);
28+
});
29+
test("matches a full https uri", () {
30+
expect(_match(matcher, 'https://proper.https/uri'), isTrue);
31+
});
32+
test("matches http: schema without path", () {
33+
expect(_match(matcher, 'http:'), isTrue);
34+
});
35+
test("matches https: schema without path", () {
36+
expect(_match(matcher, 'http:'), isTrue);
37+
});
38+
test("doesn't match null", () {
39+
expect(_match(matcher, null), isFalse);
40+
});
41+
test("doesn't match empty", () {
42+
expect(_match(matcher, ''), isFalse);
43+
});
44+
});
45+
group("custom network source matcher", () {
46+
ImageSourceMatcher matcher = networkSourceMatcher(
47+
schemas: ['https'],
48+
domains: ['www.google.com'],
49+
extension: 'png',
50+
);
51+
test("matches schema, domain and extension", () {
52+
expect(_match(matcher, 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png'), isTrue);
53+
});
54+
test("doesn't match if schema is different", () {
55+
expect(_match(matcher, 'http://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png'), isFalse);
56+
});
57+
test("doesn't match if domain is different", () {
58+
expect(_match(matcher, 'https://google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png'), isFalse);
59+
});
60+
test("doesn't match if file extension is different", () {
61+
expect(_match(matcher, 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dppng'), isFalse);
62+
});
63+
test("doesn't match null", () {
64+
expect(_match(matcher, null), isFalse);
65+
});
66+
test("doesn't match empty", () {
67+
expect(_match(matcher, ''), isFalse);
68+
});
69+
});
70+
group("base64 image data uri matcher", () {
71+
ImageSourceMatcher matcher = base64DataUriMatcher();
72+
test("matches a full png base64 data uri", () {
73+
expect(_match(matcher, 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), isTrue);
74+
});
75+
test("matches a full jpeg base64 data uri", () {
76+
expect(_match(matcher, 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDADIiJSwlHzIsKSw4NTI7S31RS0VFS5ltc1p9tZ++u7Kfr6zI4f/zyNT/16yv+v/9////////wfD/////////////2wBDATU4OEtCS5NRUZP/zq/O////////////////////////////////////////////////////////////////////wAARCAAYAEADAREAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAQMAAgQF/8QAJRABAAIBBAEEAgMAAAAAAAAAAQIRAAMSITEEEyJBgTORUWFx/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AOgM52xQDrjvAV5Xv0vfKUALlTQfeBm0HThMNHXkL0Lw/swN5qgA8yT4MCS1OEOJV8mBz9Z05yfW8iSx7p4j+jA1aD6Wj7ZMzstsfvAas4UyRHvjrAkC9KhpLMClQntlqFc2X1gUj4viwVObKrddH9YDoHvuujAEuNV+bLwFS8XxdSr+Cq3Vf+4F5RgQl6ZR2p1eAzU/HX80YBYyJLCuexwJCO2O1bwCRidAfWBSctswbI12GAJT3yiwFR7+MBjGK2g/WAJR3FdF84E2rK5VR0YH/9k='), isTrue);
77+
});
78+
test("matches base64 data uri without data", () {
79+
expect(_match(matcher, 'data:image/png;base64,'), isTrue);
80+
});
81+
test("doesn't match non-base64 image data uri", () {
82+
expect(_match(matcher, 'data:image/png;hex,89504e470d0a1a0a0000000d49484452000000050000000508060000008d6f26e50000001c4944415408d763f8ffff3fc37f062005c3201284d031f18258cd04000ef535cbd18e0e1f0000000049454e44ae426082'), isFalse);
83+
});
84+
test("doesn't match base64 non-image data uri", () {
85+
expect(_match(matcher, 'data:text/plain;base64,'), isFalse);
86+
});
87+
test("doesn't non-data schema", () {
88+
expect(_match(matcher, 'http:'), isFalse);
89+
});
90+
test("doesn't match null", () {
91+
expect(_match(matcher, null), isFalse);
92+
});
93+
test("doesn't match empty", () {
94+
expect(_match(matcher, ''), isFalse);
95+
});
96+
});
97+
}
98+
99+
dom.Element _fakeElement(String src) {
100+
return dom.Element.html("""
101+
<img src="$src" />
102+
""");
103+
}
104+
105+
bool _match(ImageSourceMatcher matcher, String src) {
106+
final element = _fakeElement(src);
107+
return matcher.call(
108+
element.attributes.map((key, value) => MapEntry(key.toString(), value)),
109+
element);
110+
}

0 commit comments

Comments
 (0)