FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
pythonnative/tests/test_animated_easing.py at main · pythonnative/pythonnative · GitHub
pythonnative
pythonnative
Repository navigation
Code
Issues
11
(11)
Pull requests
4
(4)
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
pythonnative
/
tests
/
test_animated_easing.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
182 lines (143 loc) · 6.84 KB
Breadcrumbs
pythonnative
/
tests
/
test_animated_easing.py
Copy path
File metadata and controls
182 lines (143 loc) · 6.84 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
"""Tests for ``pn.Easing``: descriptors, the Python evaluator, and the wire form."""
from
__future__
import
annotations
import
time
from
typing
import
Any
import
pytest
from
pythonnative
.
animated
import
EASING_NAMES
,
Animated
,
AnimatedValue
,
Easing
,
EasingSpec
from
pythonnative
.
native_views
import
set_backend
from
pythonnative
.
testing
import
FakeBackend
# ======================================================================
# Descriptors
# ======================================================================
def
test_easing_namespace_exposes_frozen_specs
()
->
None
:
assert
EASING_NAMES
==
(
"linear"
,
"ease"
,
"ease_in"
,
"ease_out"
,
"ease_in_out"
,
"quad"
,
"cubic"
,
"bounce"
)
for
name
in
EASING_NAMES
:
spec
=
getattr
(
Easing
,
name
)
assert
isinstance
(
spec
,
EasingSpec
)
assert
spec
.
name
==
name
and
spec
.
points
is
None
assert
spec
.
to_wire
()
==
name
with
pytest
.
raises
(
Exception
):
Easing
.
linear
.
name
=
"other"
# type: ignore[misc]
def
test_bezier_descriptor_carries_control_points
()
->
None
:
spec
=
Easing
.
bezier
(
0.2
,
0.8
,
0.2
,
1.0
)
assert
spec
==
EasingSpec
(
"bezier"
, (
0.2
,
0.8
,
0.2
,
1.0
))
assert
spec
.
to_wire
()
==
[
0.2
,
0.8
,
0.2
,
1.0
]
assert
repr
(
spec
)
==
"Easing.bezier(0.2, 0.8, 0.2, 1.0)"
assert
repr
(
Easing
.
ease_out
)
==
"Easing.ease_out"
def
test_bezier_validation
()
->
None
:
with
pytest
.
raises
(
ValueError
):
Easing
.
bezier
(
1.5
,
0.0
,
0.5
,
1.0
)
# x1 outside [0, 1]
with
pytest
.
raises
(
ValueError
):
Easing
.
bezier
(
0.5
,
0.0
,
-
0.1
,
1.0
)
# x2 outside [0, 1]
# y values may overshoot (anticipation and overshoot curves).
Easing
.
bezier
(
0.34
,
1.56
,
0.64
,
1.0
)
with
pytest
.
raises
(
ValueError
):
EasingSpec
(
"bezier"
)
with
pytest
.
raises
(
ValueError
):
EasingSpec
(
"wobble"
)
with
pytest
.
raises
(
ValueError
):
EasingSpec
(
"linear"
, (
0.0
,
0.0
,
1.0
,
1.0
))
# ======================================================================
# Evaluator
# ======================================================================
def
test_named_curves_evaluate_to_reference_values
()
->
None
:
assert
Easing
.
linear
.
evaluate
(
0.3
)
==
0.3
assert
Easing
.
quad
.
evaluate
(
0.5
)
==
0.25
assert
Easing
.
cubic
.
evaluate
(
0.5
)
==
0.125
assert
Easing
.
bounce
.
evaluate
(
0.0
)
==
0.0
assert
abs
(
Easing
.
bounce
.
evaluate
(
1.0
)
-
1.0
)
<
1e-12
# Penner bounce-out midway through the first arc.
assert
abs
(
Easing
.
bounce
.
evaluate
(
0.2
)
-
7.5625
*
0.2
*
0.2
)
<
1e-12
for
name
in
EASING_NAMES
:
spec
=
getattr
(
Easing
,
name
)
assert
spec
.
evaluate
(
0.0
)
==
0.0
assert
abs
(
spec
.
evaluate
(
1.0
)
-
1.0
)
<
1e-9
def
test_ease_family_matches_react_native_definitions
()
->
None
:
# ease == bezier(0.42, 0, 1, 1) (React Native's Easing.ease); in/out/in_out derive from it.
for
t
in
(
0.1
,
0.25
,
0.5
,
0.75
,
0.9
):
assert
abs
(
Easing
.
ease
.
evaluate
(
t
)
-
Easing
.
bezier
(
0.42
,
0.0
,
1.0
,
1.0
).
evaluate
(
t
))
<
1e-9
assert
abs
(
Easing
.
ease_in
.
evaluate
(
t
)
-
Easing
.
ease
.
evaluate
(
t
))
<
1e-9
# Easing.out(f)(t) == 1 - f(1 - t)
assert
abs
(
Easing
.
ease_out
.
evaluate
(
t
)
-
(
1.0
-
Easing
.
ease
.
evaluate
(
1.0
-
t
)))
<
1e-6
assert
Easing
.
ease_in
.
evaluate
(
0.5
)
<
0.5
<
Easing
.
ease_out
.
evaluate
(
0.5
)
assert
abs
(
Easing
.
ease_in_out
.
evaluate
(
0.5
)
-
0.5
)
<
1e-6
assert
Easing
.
ease_in_out
.
evaluate
(
0.25
)
<
0.25
and
Easing
.
ease_in_out
.
evaluate
(
0.75
)
>
0.75
def
test_cubic_bezier_solver_inverts_the_parametric_curve
()
->
None
:
"""For sampled parameter values, evaluate(x(t)) must return y(t)."""
def
component
(
t
:
float
,
p1
:
float
,
p2
:
float
)
->
float
:
inv
=
1.0
-
t
return
3
*
inv
*
inv
*
t
*
p1
+
3
*
inv
*
t
*
t
*
p2
+
t
*
t
*
t
curves
=
[
(
0.2
,
0.8
,
0.2
,
1.0
),
(
0.42
,
0.0
,
0.58
,
1.0
),
(
0.34
,
1.56
,
0.64
,
1.0
),
(
1.0
,
0.0
,
0.0
,
1.0
),
(
0.0
,
0.0
,
1.0
,
1.0
),
]
for
x1
,
y1
,
x2
,
y2
in
curves
:
spec
=
Easing
.
bezier
(
x1
,
y1
,
x2
,
y2
)
for
i
in
range
(
1
,
50
):
t
=
i
/
50
x
=
component
(
t
,
x1
,
x2
)
y
=
component
(
t
,
y1
,
y2
)
assert
abs
(
spec
.
evaluate
(
x
)
-
y
)
<
1e-5
, (
x1
,
y1
,
x2
,
y2
,
t
)
def
test_bezier_clamps_progress_outside_unit_interval
()
->
None
:
spec
=
Easing
.
bezier
(
0.2
,
0.8
,
0.2
,
1.0
)
assert
spec
.
evaluate
(
-
0.5
)
==
0.0
assert
spec
.
evaluate
(
1.5
)
==
1.0
# ======================================================================
# Animated.timing integration
# ======================================================================
class
_RecordingBackend
(
FakeBackend
):
def
__init__
(
self
)
->
None
:
super
().
__init__
()
self
.
native_started
:
list
=
[]
def
start_animation
(
self
,
tag
:
int
,
anim_id
:
int
,
prop_name
:
str
,
spec
:
Any
)
->
bool
:
self
.
native_started
.
append
((
tag
,
anim_id
,
prop_name
,
dict
(
spec
)))
return
True
def
cancel_animation
(
self
,
tag
:
int
,
anim_id
:
int
)
->
Any
:
return
None
@
pytest
.
fixture
def
backend
():
# type: ignore[no-untyped-def]
backend
=
_RecordingBackend
()
set_backend
(
backend
)
try
:
yield
backend
finally
:
set_backend
(
None
)
def
test_timing_rejects_unknown_easing_names
()
->
None
:
v
=
AnimatedValue
(
0.0
)
with
pytest
.
raises
(
ValueError
,
match
=
"Unknown easing"
):
Animated
.
timing
(
v
,
to
=
1.0
,
easing
=
"ease_in_quad"
)
with
pytest
.
raises
(
ValueError
):
Animated
.
timing
(
v
,
to
=
1.0
,
easing
=
"eas_in_out"
)
with
pytest
.
raises
(
TypeError
):
Animated
.
timing
(
v
,
to
=
1.0
,
easing
=
42
)
# type: ignore[arg-type]
def
test_timing_serializes_named_and_bezier_easings
(
backend
:
_RecordingBackend
)
->
None
:
v
=
AnimatedValue
(
0.0
)
v
.
attach
(
7
,
"opacity"
)
Animated
.
timing
(
v
,
to
=
1.0
,
duration
=
500
,
easing
=
"ease_out"
).
start
()
Animated
.
timing
(
v
,
to
=
1.0
,
duration
=
500
,
easing
=
Easing
.
bounce
).
start
()
Animated
.
timing
(
v
,
to
=
1.0
,
duration
=
500
,
easing
=
Easing
.
bezier
(
0.2
,
0.8
,
0.2
,
1.0
)).
start
()
Animated
.
timing
(
v
,
to
=
1.0
,
duration
=
500
).
start
()
wire
=
[
spec
[
"easing"
]
for
_tag
,
_id
,
_prop
,
spec
in
backend
.
native_started
]
assert
wire
==
[
"ease_out"
,
"bounce"
, [
0.2
,
0.8
,
0.2
,
1.0
],
"ease_in_out"
]
def
test_callable_easing_disables_the_native_driver
(
backend
:
_RecordingBackend
)
->
None
:
v
=
AnimatedValue
(
0.0
)
v
.
attach
(
7
,
"opacity"
)
handle
=
Animated
.
timing
(
v
,
to
=
1.0
,
duration
=
30
,
easing
=
lambda
t
:
t
*
t
)
handle
.
start
()
assert
backend
.
native_started
==
[]
deadline
=
time
.
monotonic
()
+
2.0
while
time
.
monotonic
()
<
deadline
and
v
.
value
<
0.99
:
time
.
sleep
(
0.01
)
assert
abs
(
v
.
value
-
1.0
)
<
0.05
@
pytest
.
mark
.
asyncio
async
def
test_timing_with_bezier_easing_runs_on_python_ticker
()
->
None
:
v
=
AnimatedValue
(
0.0
)
seen
:
list
=
[]
v
.
add_listener
(
"x"
,
seen
.
append
)
result
=
await
Animated
.
timing
(
v
,
to
=
1.0
,
duration
=
60
,
easing
=
Easing
.
bezier
(
0.2
,
0.8
,
0.2
,
1.0
))
assert
result
.
finished
is
True
assert
abs
(
v
.
value
-
1.0
)
<
1e-9
assert
seen
==
sorted
(
seen
),
"an ease-out style bezier should be monotonic"
Back
|
FazBrowse Home
|
New Git URL