Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
9cb2953e
Unverified
Commit
9cb2953e
authored
Feb 10, 2020
by
Dan Field
Committed by
GitHub
Feb 10, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix image tests that make faulty assumptions about lifecycle of image provider (#50297)
parent
56817279
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
203 additions
and
10 deletions
+203
-10
image_test.dart
packages/flutter/test/widgets/image_test.dart
+203
-10
No files found.
packages/flutter/test/widgets/image_test.dart
View file @
9cb2953e
...
...
@@ -187,7 +187,9 @@ void main() {
final
GlobalKey
mediaQueryKey1
=
GlobalKey
(
debugLabel:
'mediaQueryKey1'
);
final
GlobalKey
mediaQueryKey2
=
GlobalKey
(
debugLabel:
'mediaQueryKey2'
);
final
GlobalKey
imageKey
=
GlobalKey
(
debugLabel:
'image'
);
final
TestImageProvider
imageProvider
=
TestImageProvider
();
final
ConfigurationKeyedTestImageProvider
imageProvider
=
ConfigurationKeyedTestImageProvider
();
final
Set
<
Object
>
seenKeys
=
<
Object
>{};
final
DebouncingImageProvider
debouncingProvider
=
DebouncingImageProvider
(
imageProvider
,
seenKeys
);
// Of the two nested MediaQuery objects, the innermost one,
// mediaQuery2, should define the configuration of the imageProvider.
...
...
@@ -207,7 +209,7 @@ void main() {
child:
Image
(
excludeFromSemantics:
true
,
key:
imageKey
,
image:
image
Provider
,
image:
debouncing
Provider
,
),
),
),
...
...
@@ -234,7 +236,7 @@ void main() {
child:
Image
(
excludeFromSemantics:
true
,
key:
imageKey
,
image:
image
Provider
,
image:
debouncing
Provider
,
),
),
),
...
...
@@ -247,7 +249,9 @@ void main() {
final
GlobalKey
mediaQueryKey1
=
GlobalKey
(
debugLabel:
'mediaQueryKey1'
);
final
GlobalKey
mediaQueryKey2
=
GlobalKey
(
debugLabel:
'mediaQueryKey2'
);
final
GlobalKey
imageKey
=
GlobalKey
(
debugLabel:
'image'
);
final
TestImageProvider
imageProvider
=
TestImageProvider
();
final
ConfigurationKeyedTestImageProvider
imageProvider
=
ConfigurationKeyedTestImageProvider
();
final
Set
<
Object
>
seenKeys
=
<
Object
>{};
final
DebouncingImageProvider
debouncingProvider
=
DebouncingImageProvider
(
imageProvider
,
seenKeys
);
// This is just a variation on the previous test. In this version the location
// of the Image changes and the MediaQuery widgets do not.
...
...
@@ -264,7 +268,7 @@ void main() {
child:
Image
(
excludeFromSemantics:
true
,
key:
imageKey
,
image:
image
Provider
,
image:
debouncing
Provider
,
),
),
MediaQuery
(
...
...
@@ -302,7 +306,7 @@ void main() {
child:
Image
(
excludeFromSemantics:
true
,
key:
imageKey
,
image:
image
Provider
,
image:
debouncing
Provider
,
),
),
],
...
...
@@ -312,6 +316,139 @@ void main() {
expect
(
imageProvider
.
_lastResolvedConfiguration
.
devicePixelRatio
,
10.0
);
});
testWidgets
(
'Verify ImageProvider does not inherit configuration when it does not key to it'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
mediaQueryKey1
=
GlobalKey
(
debugLabel:
'mediaQueryKey1'
);
final
GlobalKey
mediaQueryKey2
=
GlobalKey
(
debugLabel:
'mediaQueryKey2'
);
final
GlobalKey
imageKey
=
GlobalKey
(
debugLabel:
'image'
);
final
TestImageProvider
imageProvider
=
TestImageProvider
();
final
Set
<
Object
>
seenKeys
=
<
Object
>{};
final
DebouncingImageProvider
debouncingProvider
=
DebouncingImageProvider
(
imageProvider
,
seenKeys
);
// Of the two nested MediaQuery objects, the innermost one,
// mediaQuery2, should define the configuration of the imageProvider.
await
tester
.
pumpWidget
(
MediaQuery
(
key:
mediaQueryKey1
,
data:
const
MediaQueryData
(
devicePixelRatio:
10.0
,
padding:
EdgeInsets
.
zero
,
),
child:
MediaQuery
(
key:
mediaQueryKey2
,
data:
const
MediaQueryData
(
devicePixelRatio:
5.0
,
padding:
EdgeInsets
.
zero
,
),
child:
Image
(
excludeFromSemantics:
true
,
key:
imageKey
,
image:
debouncingProvider
,
),
),
),
);
expect
(
imageProvider
.
_lastResolvedConfiguration
.
devicePixelRatio
,
5.0
);
// This is the same widget hierarchy as before except that the
// two MediaQuery objects have exchanged places. The imageProvider
// should not be resolved again, because it does not key to configuration.
await
tester
.
pumpWidget
(
MediaQuery
(
key:
mediaQueryKey2
,
data:
const
MediaQueryData
(
devicePixelRatio:
5.0
,
padding:
EdgeInsets
.
zero
,
),
child:
MediaQuery
(
key:
mediaQueryKey1
,
data:
const
MediaQueryData
(
devicePixelRatio:
10.0
,
padding:
EdgeInsets
.
zero
,
),
child:
Image
(
excludeFromSemantics:
true
,
key:
imageKey
,
image:
debouncingProvider
,
),
),
),
);
expect
(
imageProvider
.
_lastResolvedConfiguration
.
devicePixelRatio
,
5.0
);
});
testWidgets
(
'Verify ImageProvider does not inherit configuration when it does not key to it again'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
mediaQueryKey1
=
GlobalKey
(
debugLabel:
'mediaQueryKey1'
);
final
GlobalKey
mediaQueryKey2
=
GlobalKey
(
debugLabel:
'mediaQueryKey2'
);
final
GlobalKey
imageKey
=
GlobalKey
(
debugLabel:
'image'
);
final
TestImageProvider
imageProvider
=
TestImageProvider
();
final
Set
<
Object
>
seenKeys
=
<
Object
>{};
final
DebouncingImageProvider
debouncingProvider
=
DebouncingImageProvider
(
imageProvider
,
seenKeys
);
// This is just a variation on the previous test. In this version the location
// of the Image changes and the MediaQuery widgets do not.
await
tester
.
pumpWidget
(
Row
(
textDirection:
TextDirection
.
ltr
,
children:
<
Widget
>
[
MediaQuery
(
key:
mediaQueryKey2
,
data:
const
MediaQueryData
(
devicePixelRatio:
5.0
,
padding:
EdgeInsets
.
zero
,
),
child:
Image
(
excludeFromSemantics:
true
,
key:
imageKey
,
image:
debouncingProvider
,
),
),
MediaQuery
(
key:
mediaQueryKey1
,
data:
const
MediaQueryData
(
devicePixelRatio:
10.0
,
padding:
EdgeInsets
.
zero
,
),
child:
Container
(
width:
100.0
),
),
],
),
);
expect
(
imageProvider
.
_lastResolvedConfiguration
.
devicePixelRatio
,
5.0
);
await
tester
.
pumpWidget
(
Row
(
textDirection:
TextDirection
.
ltr
,
children:
<
Widget
>
[
MediaQuery
(
key:
mediaQueryKey2
,
data:
const
MediaQueryData
(
devicePixelRatio:
5.0
,
padding:
EdgeInsets
.
zero
,
),
child:
Container
(
width:
100.0
),
),
MediaQuery
(
key:
mediaQueryKey1
,
data:
const
MediaQueryData
(
devicePixelRatio:
10.0
,
padding:
EdgeInsets
.
zero
,
),
child:
Image
(
excludeFromSemantics:
true
,
key:
imageKey
,
image:
debouncingProvider
,
),
),
],
),
);
expect
(
imageProvider
.
_lastResolvedConfiguration
.
devicePixelRatio
,
5.0
);
});
testWidgets
(
'Verify Image stops listening to ImageStream'
,
(
WidgetTester
tester
)
async
{
final
TestImageProvider
imageProvider
=
TestImageProvider
();
await
tester
.
pumpWidget
(
Image
(
image:
imageProvider
,
excludeFromSemantics:
true
));
...
...
@@ -1229,7 +1366,36 @@ void main() {
});
}
class
TestImageProvider
extends
ImageProvider
<
TestImageProvider
>
{
class
ConfigurationAwareKey
{
const
ConfigurationAwareKey
(
this
.
provider
,
this
.
configuration
)
:
assert
(
provider
!=
null
),
assert
(
configuration
!=
null
);
final
ImageProvider
provider
;
final
ImageConfiguration
configuration
;
@override
bool
operator
==(
Object
other
)
{
if
(
other
.
runtimeType
!=
runtimeType
)
{
return
false
;
}
return
other
is
ConfigurationAwareKey
&&
other
.
provider
==
provider
&&
other
.
configuration
==
configuration
;
}
@override
int
get
hashCode
=>
hashValues
(
provider
,
configuration
);
}
class
ConfigurationKeyedTestImageProvider
extends
TestImageProvider
{
@override
Future
<
ConfigurationAwareKey
>
obtainKey
(
ImageConfiguration
configuration
)
{
return
SynchronousFuture
<
ConfigurationAwareKey
>(
ConfigurationAwareKey
(
this
,
configuration
));
}
}
class
TestImageProvider
extends
ImageProvider
<
Object
>
{
TestImageProvider
({
ImageStreamCompleter
streamCompleter
})
{
_streamCompleter
=
streamCompleter
??
OneFrameImageStreamCompleter
(
_completer
.
future
);
...
...
@@ -1243,18 +1409,18 @@ class TestImageProvider extends ImageProvider<TestImageProvider> {
bool
_loadCalled
=
false
;
@override
Future
<
TestImageProvider
>
obtainKey
(
ImageConfiguration
configuration
)
{
Future
<
Object
>
obtainKey
(
ImageConfiguration
configuration
)
{
return
SynchronousFuture
<
TestImageProvider
>(
this
);
}
@override
void
resolveStreamForKey
(
ImageConfiguration
configuration
,
ImageStream
stream
,
TestImageProvider
key
,
ImageErrorListener
handleError
)
{
void
resolveStreamForKey
(
ImageConfiguration
configuration
,
ImageStream
stream
,
Object
key
,
ImageErrorListener
handleError
)
{
_lastResolvedConfiguration
=
configuration
;
super
.
resolveStreamForKey
(
configuration
,
stream
,
key
,
handleError
);
}
@override
ImageStreamCompleter
load
(
TestImageProvider
key
,
DecoderCallback
decode
)
{
ImageStreamCompleter
load
(
Object
key
,
DecoderCallback
decode
)
{
_loadCalled
=
true
;
return
_streamCompleter
;
}
...
...
@@ -1327,3 +1493,30 @@ class TestImage implements ui.Image {
@override
String
toString
()
=>
'[
$width
\
u00D7
$height
]'
;
}
class
DebouncingImageProvider
extends
ImageProvider
<
Object
>
{
DebouncingImageProvider
(
this
.
imageProvider
,
this
.
seenKeys
);
/// A set of keys that will only get resolved the _first_ time they are seen.
///
/// If an ImageProvider produces the same key for two different image
/// configurations, it should only actually resolve once using this provider.
/// However, if it does care about image configuration, it should make the
/// property or properties it cares about part of the key material it
/// produces.
final
Set
<
Object
>
seenKeys
;
final
ImageProvider
<
Object
>
imageProvider
;
@override
void
resolveStreamForKey
(
ImageConfiguration
configuration
,
ImageStream
stream
,
Object
key
,
ImageErrorListener
handleError
)
{
if
(
seenKeys
.
add
(
key
))
{
imageProvider
.
resolveStreamForKey
(
configuration
,
stream
,
key
,
handleError
);
}
}
@override
Future
<
Object
>
obtainKey
(
ImageConfiguration
configuration
)
=>
imageProvider
.
obtainKey
(
configuration
);
@override
ImageStreamCompleter
load
(
Object
key
,
DecoderCallback
decode
)
=>
imageProvider
.
load
(
key
,
decode
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment