11"""A mocked Airtable API wrapper."""
22from unittest import mock
3+ from pyairtable .formulas import match
34from requests .exceptions import HTTPError
45
56def get_mock_airtable ():
67 """
78 Wrap it in a function, so it's pure
89 """
910
10- class MockAirtable (mock .Mock ):
11- def get_iter (self ):
12- return [self .get_all ()]
11+ class MockTable (mock .Mock ):
12+ def iterate (self ):
13+ return [self .all ()]
1314
1415
15- MockAirtable .table_name = "app_airtable_advert_base_key"
16+ MockTable .table_name = "app_airtable_advert_base_key"
1617
17- MockAirtable .get = mock .MagicMock ("get" )
18+ MockTable .get = mock .MagicMock ("get" )
1819
1920 def get_fn (record_id ):
2021 if record_id == "recNewRecordId" :
@@ -34,11 +35,11 @@ def get_fn(record_id):
3435 else :
3536 raise HTTPError ("404 Client Error: Not Found" )
3637
37- MockAirtable .get .side_effect = get_fn
38+ MockTable .get .side_effect = get_fn
3839
39- MockAirtable . insert = mock .MagicMock ("insert " )
40+ MockTable . create = mock .MagicMock ("create " )
4041
41- MockAirtable . insert .return_value = {
42+ MockTable . create .return_value = {
4243 "id" : "recNewRecordId" ,
4344 "fields" : {
4445 "title" : "Red! It's the new blue!" ,
@@ -52,8 +53,8 @@ def get_fn(record_id):
5253 },
5354 }
5455
55- MockAirtable .update = mock .MagicMock ("update" )
56- MockAirtable .update .return_value = {
56+ MockTable .update = mock .MagicMock ("update" )
57+ MockTable .update .return_value = {
5758 "id" : "recNewRecordId" ,
5859 "fields" : {
5960 "title" : "Red! It's the new blue!" ,
@@ -67,12 +68,77 @@ def get_fn(record_id):
6768 },
6869 }
6970
70- MockAirtable .delete = mock .MagicMock ("delete" )
71- MockAirtable .delete .return_value = {"deleted" : True , "record" : "recNewRecordId" }
71+ MockTable .delete = mock .MagicMock ("delete" )
72+ MockTable .delete .return_value = {"deleted" : True , "record" : "recNewRecordId" }
7273
73- MockAirtable .search = mock .MagicMock ("search" )
74- def search_fn (field , value ):
75- if field == "slug" and value == "red-its-new-blue" :
74+ MockTable .all = mock .MagicMock ("all" )
75+ def all_fn (formula = None ):
76+ if formula is None :
77+ return [
78+ {
79+ "id" : "recNewRecordId" ,
80+ "fields" : {
81+ "title" : "Red! It's the new blue!" ,
82+ "description" : "Red is a scientifically proven color that moves faster than all other colors." ,
83+ "external_link" : "https://example.com/" ,
84+ "is_active" : True ,
85+ "rating" : "1.5" ,
86+ "long_description" : "<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Veniam laboriosam consequatur saepe. Repellat itaque dolores neque, impedit reprehenderit eum culpa voluptates harum sapiente nesciunt ratione.</p>" ,
87+ "points" : 95 ,
88+ "slug" : "delete-me" ,
89+ "publications" : [
90+ {"title" : "Record 1 publication 1" },
91+ {"title" : "Record 1 publication 2" },
92+ {"title" : "Record 1 publication 3" },
93+ ]
94+ },
95+ },
96+ {
97+ "id" : "Different record" ,
98+ "fields" : {
99+ "title" : "Not the used record." ,
100+ "description" : "This is only used for multiple responses from MockAirtable" ,
101+ "external_link" : "https://example.com/" ,
102+ "is_active" : False ,
103+ "rating" : "5.5" ,
104+ "long_description" : "" ,
105+ "points" : 1 ,
106+ "slug" : "not-the-used-record" ,
107+ },
108+ },
109+ {
110+ "id" : "recRecordThree" ,
111+ "fields" : {
112+ "title" : "A third record." ,
113+ "description" : "This is only used for multiple responses from MockAirtable" ,
114+ "external_link" : "https://example.com/" ,
115+ "is_active" : False ,
116+ "rating" : "5.5" ,
117+ "long_description" : "" ,
118+ "points" : 1 ,
119+ "slug" : "record-3" ,
120+ },
121+ },
122+ {
123+ "id" : "recRecordFour" ,
124+ "fields" : {
125+ "title" : "A fourth record." ,
126+ "description" : "This is only used for multiple responses from MockAirtable" ,
127+ "external_link" : "https://example.com/" ,
128+ "is_active" : False ,
129+ "rating" : "5.5" ,
130+ "long_description" : "" ,
131+ "points" : 1 ,
132+ "slug" : "record-4" ,
133+ "publications" : [
134+ {"title" : "Record 4 publication 1" },
135+ {"title" : "Record 4 publication 2" },
136+ {"title" : "Record 4 publication 3" },
137+ ]
138+ },
139+ },
140+ ]
141+ elif formula == match ({"slug" : "red-its-new-blue" }):
76142 return [
77143 {
78144 "id" : "recNewRecordId" ,
@@ -101,7 +167,7 @@ def search_fn(field, value):
101167 },
102168 },
103169 ]
104- elif field == "slug" and value == "a-matching-slug" :
170+ elif formula == match ({ "slug" : "a-matching-slug" }) :
105171 return [
106172 {
107173 "id" : "recMatchedRecordId" ,
@@ -117,7 +183,7 @@ def search_fn(field, value):
117183 },
118184 },
119185 ]
120- elif field == "Page Slug" and value == "home" :
186+ elif formula == match ({ "Page Slug" : "home" }) :
121187 return [
122188 {
123189 "id" : "recHomePageId" ,
@@ -131,72 +197,14 @@ def search_fn(field, value):
131197 else :
132198 return []
133199
134- MockAirtable .search .side_effect = search_fn
135-
136- MockAirtable .get_all = mock .MagicMock ("get_all" )
137- MockAirtable .get_all .return_value = [
138- {
139- "id" : "recNewRecordId" ,
140- "fields" : {
141- "title" : "Red! It's the new blue!" ,
142- "description" : "Red is a scientifically proven color that moves faster than all other colors." ,
143- "external_link" : "https://example.com/" ,
144- "is_active" : True ,
145- "rating" : "1.5" ,
146- "long_description" : "<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Veniam laboriosam consequatur saepe. Repellat itaque dolores neque, impedit reprehenderit eum culpa voluptates harum sapiente nesciunt ratione.</p>" ,
147- "points" : 95 ,
148- "slug" : "delete-me" ,
149- "publications" : [
150- {"title" : "Record 1 publication 1" },
151- {"title" : "Record 1 publication 2" },
152- {"title" : "Record 1 publication 3" },
153- ]
154- },
155- },
156- {
157- "id" : "Different record" ,
158- "fields" : {
159- "title" : "Not the used record." ,
160- "description" : "This is only used for multiple responses from MockAirtable" ,
161- "external_link" : "https://example.com/" ,
162- "is_active" : False ,
163- "rating" : "5.5" ,
164- "long_description" : "" ,
165- "points" : 1 ,
166- "slug" : "not-the-used-record" ,
167- },
168- },
169- {
170- "id" : "recRecordThree" ,
171- "fields" : {
172- "title" : "A third record." ,
173- "description" : "This is only used for multiple responses from MockAirtable" ,
174- "external_link" : "https://example.com/" ,
175- "is_active" : False ,
176- "rating" : "5.5" ,
177- "long_description" : "" ,
178- "points" : 1 ,
179- "slug" : "record-3" ,
180- },
181- },
182- {
183- "id" : "recRecordFour" ,
184- "fields" : {
185- "title" : "A fourth record." ,
186- "description" : "This is only used for multiple responses from MockAirtable" ,
187- "external_link" : "https://example.com/" ,
188- "is_active" : False ,
189- "rating" : "5.5" ,
190- "long_description" : "" ,
191- "points" : 1 ,
192- "slug" : "record-4" ,
193- "publications" : [
194- {"title" : "Record 4 publication 1" },
195- {"title" : "Record 4 publication 2" },
196- {"title" : "Record 4 publication 3" },
197- ]
198- },
199- },
200- ]
200+ MockTable .all .side_effect = all_fn
201+
202+ class MockApi (mock .Mock ):
203+ def __init__ (self , * args , ** kwargs ):
204+ super ().__init__ (* args , ** kwargs )
205+ self ._table = MockTable ()
206+
207+ def table (self , base_id , table_name ):
208+ return self ._table
201209
202- return MockAirtable
210+ return MockApi
0 commit comments