3
3
"""
4
4
5
5
import unittest
6
- from unittest .mock import Mock
7
- from flask import Flask , Request
6
+ from flask import Flask , Request , jsonify as _jsonify
8
7
from werkzeug .test import EnvironBuilder
9
8
10
9
from firebase_functions import core , https_fn
@@ -25,7 +24,9 @@ def init():
25
24
nonlocal hello
26
25
hello = "world"
27
26
28
- func = Mock (__name__ = "example_func" )
27
+ @https_fn .on_request ()
28
+ def func (_ ):
29
+ pass
29
30
30
31
with app .test_request_context ("/" ):
31
32
environ = EnvironBuilder (
@@ -37,9 +38,8 @@ def init():
37
38
},
38
39
).get_environ ()
39
40
request = Request (environ )
40
- decorated_func = https_fn .on_request ()(func )
41
41
42
- decorated_func (request )
42
+ func (request )
43
43
44
44
self .assertEqual (hello , "world" )
45
45
@@ -53,7 +53,9 @@ def init():
53
53
nonlocal hello
54
54
hello = "world"
55
55
56
- func = Mock (__name__ = "example_func" )
56
+ @https_fn .on_call ()
57
+ def func (_ ):
58
+ pass
57
59
58
60
with app .test_request_context ("/" ):
59
61
environ = EnvironBuilder (
@@ -65,8 +67,145 @@ def init():
65
67
},
66
68
).get_environ ()
67
69
request = Request (environ )
68
- decorated_func = https_fn .on_call ()(func )
69
-
70
- decorated_func (request )
70
+ func (request )
71
71
72
72
self .assertEqual ("world" , hello )
73
+
74
+ def test_callable_encoding (self ):
75
+ app = Flask (__name__ )
76
+
77
+ @https_fn .on_call ()
78
+ def add (req : https_fn .CallableRequest [int ]):
79
+ return req .data + 1
80
+
81
+ with app .test_request_context ("/" ):
82
+ environ = EnvironBuilder (
83
+ method = "POST" ,
84
+ json = {
85
+ "data" : 1
86
+ }
87
+ ).get_environ ()
88
+ request = Request (environ )
89
+
90
+ response = add (request )
91
+ self .assertEqual (response .status_code , 200 )
92
+ self .assertEqual (response .get_json (), { "result" : 2 })
93
+
94
+ def test_callable_errors (self ):
95
+ app = Flask (__name__ )
96
+
97
+ @https_fn .on_call ()
98
+ def throw_generic_error (req ):
99
+ raise Exception ("Invalid type" )
100
+
101
+ @https_fn .on_call ()
102
+ def throw_access_denied (req ):
103
+ raise https_fn .HttpsError (https_fn .FunctionsErrorCode .PERMISSION_DENIED , "Permission is denied" )
104
+
105
+ with app .test_request_context ("/" ):
106
+ environ = EnvironBuilder (
107
+ method = "POST" ,
108
+ json = {
109
+ "data" : None
110
+ }
111
+ ).get_environ ()
112
+ request = Request (environ )
113
+
114
+ response = throw_generic_error (request )
115
+ self .assertEqual (response .status_code , 500 )
116
+ self .assertEqual (response .get_json (), { "error" : { "message" : "INTERNAL" , "status" : "INTERNAL" } })
117
+
118
+ response = throw_access_denied (request )
119
+ self .assertEqual (response .status_code , 403 )
120
+ self .assertEqual (response .get_json (), { "error" : { "message" : "Permission is denied" , "status" : "PERMISSION_DENIED" }})
121
+
122
+ def test_yielding_without_streaming (self ):
123
+ app = Flask (__name__ )
124
+
125
+ @https_fn .on_call ()
126
+ def yielder (req : https_fn .CallableRequest [int ]):
127
+ yield from range (req .data )
128
+ return "OK"
129
+
130
+ @https_fn .on_call ()
131
+ def yield_thrower (req : https_fn .CallableRequest [int ]):
132
+ yield from range (req .data )
133
+ raise https_fn .HttpsError (https_fn .FunctionsErrorCode .PERMISSION_DENIED , "Can't read anymore" )
134
+
135
+ with app .test_request_context ("/" ):
136
+ environ = EnvironBuilder (
137
+ method = "POST" ,
138
+ json = {
139
+ "data" : 5
140
+ }
141
+ ).get_environ ()
142
+
143
+ request = Request (environ )
144
+ response = yielder (request )
145
+
146
+ self .assertEqual (response .status_code , 200 )
147
+ self .assertEqual (response .get_json (), { "result" : "OK" })
148
+
149
+ with app .test_request_context ("/" ):
150
+ environ = EnvironBuilder (
151
+ method = "POST" ,
152
+ json = {
153
+ "data" : 3
154
+ }
155
+ ).get_environ ()
156
+
157
+ request = Request (environ )
158
+ response = yield_thrower (request )
159
+
160
+ self .assertEqual (response .status_code , 403 )
161
+ self .assertEqual (response .get_json (), { "error" : { "message" : "Can't read anymore" , "status" : "PERMISSION_DENIED" }})
162
+
163
+
164
+ def test_yielding_with_streaming (self ):
165
+ app = Flask (__name__ )
166
+
167
+ @https_fn .on_call ()
168
+ def yielder (req : https_fn .CallableRequest [int ]):
169
+ yield from range (req .data )
170
+ return "OK"
171
+
172
+ @https_fn .on_call ()
173
+ def yield_thrower (req : https_fn .CallableRequest [int ]):
174
+ yield from range (req .data )
175
+ raise https_fn .HttpsError (https_fn .FunctionsErrorCode .INTERNAL , "Throwing" )
176
+
177
+ with app .test_request_context ("/" ):
178
+ environ = EnvironBuilder (
179
+ method = "POST" ,
180
+ json = {
181
+ "data" : 2
182
+ },
183
+ headers = {
184
+ "accept" : "text/event-stream"
185
+ }
186
+ ).get_environ ()
187
+
188
+ request = Request (environ )
189
+ response = yielder (request )
190
+
191
+ self .assertEqual (response .status_code , 200 )
192
+ chunks = list (response .response )
193
+ self .assertEqual (chunks , ['data: {"message": 0}\n \n ' , 'data: {"message": 1}\n \n ' , 'data: {"result": "OK"}\n \n ' , "END" ])
194
+
195
+ with app .test_request_context ("/" ):
196
+ environ = EnvironBuilder (
197
+ method = "POST" ,
198
+ json = {
199
+ "data" : 2
200
+ },
201
+ headers = {
202
+ "accept" : "text/event-stream"
203
+ }
204
+ ).get_environ ()
205
+
206
+ request = Request (environ )
207
+ response = yield_thrower (request )
208
+
209
+ self .assertEqual (response .status_code , 200 )
210
+ chunks = list (response .response )
211
+ self .assertEqual (chunks , ['data: {"message": 0}\n \n ' , 'data: {"message": 1}\n \n ' , 'error: {"error": {"status": "INTERNAL", "message": "Throwing"}}\n \n ' , "END" ])
0 commit comments