No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_leobject.py 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. """
  2. Tests for _LeObject and LeObject
  3. """
  4. import unittest
  5. from unittest import TestCase
  6. from unittest.mock import patch
  7. import EditorialModel
  8. import leapi
  9. import leapi.test.utils
  10. from leapi.leobject import _LeObject
  11. ## Testing methods that need the generated code
  12. class LeObjectTestCase(TestCase):
  13. @classmethod
  14. def setUpClass(cls):
  15. """ Write the generated code in a temporary directory and import it """
  16. cls.tmpdir = leapi.test.utils.tmp_load_factory_code()
  17. @classmethod
  18. def tearDownClass(cls):
  19. """ Remove the temporary directory created at class setup """
  20. leapi.test.utils.cleanup(cls.tmpdir)
  21. def test_uid2leobj(self):
  22. """ Testing _Leobject.uid2leobj() """
  23. import dyncode
  24. for i in dyncode.LeObject._me_uid.keys():
  25. cls = dyncode.LeObject.uid2leobj(i)
  26. if leapi.letype.LeType in cls.__bases__:
  27. self.assertEqual(i, cls._type_id)
  28. elif leapi.leclass.LeClass in cls.__bases__:
  29. self.assertEqual(i, cls._class_id)
  30. else:
  31. self.fail("Bad value returned : '%s'"%cls)
  32. i=10
  33. while i in dyncode.LeObject._me_uid.keys():
  34. i+=1
  35. with self.assertRaises(KeyError):
  36. dyncode.LeObject.uid2leobj(i)
  37. @unittest.skip("Obsolete but may be usefull for datasources tests")
  38. def test_prepare_targets(self):
  39. """ Testing _prepare_targets() method """
  40. from dyncode import Publication, Numero, LeObject
  41. test_v = {
  42. (None, None) : (None, None),
  43. (Publication, Numero): (Publication, Numero),
  44. (Publication, None): (Publication, None),
  45. (None, Numero): (Publication, Numero),
  46. (Publication,'Numero'): (Publication, Numero),
  47. ('Publication', Numero): (Publication, Numero),
  48. ('Publication', 'Numero'): (Publication, Numero),
  49. ('Publication', None): (Publication, None),
  50. (None, 'Numero'): (Publication, Numero),
  51. }
  52. for (leclass, letype), (rleclass, rletype) in test_v.items():
  53. self.assertEqual((rletype,rleclass), LeObject._prepare_targets(letype, leclass))
  54. @unittest.skip("Obsolete but may be usefull for datasources tests")
  55. def test_invalid_prepare_targets(self):
  56. """ Testing _prepare_targets() method with invalid arguments """
  57. from dyncode import Publication, Numero, LeObject, Personnes
  58. test_v = [
  59. ('',''),
  60. (Personnes, Numero),
  61. (leapi.leclass.LeClass, Numero),
  62. (Publication, leapi.letype.LeType),
  63. ('foobar', Numero),
  64. (Publication, 'foobar'),
  65. (Numero, Numero),
  66. (Publication, Publication),
  67. (None, Publication),
  68. ('foobar', 'foobar'),
  69. (42,1337),
  70. (type, Numero),
  71. (LeObject, Numero),
  72. (LeObject, LeObject),
  73. (Publication, LeObject),
  74. ]
  75. for (leclass, letype) in test_v:
  76. with self.assertRaises(ValueError):
  77. LeObject._prepare_targets(letype, leclass)
  78. @unittest.skip("Obsolete, the method should be deleted soon")
  79. def test_check_fields(self):
  80. """ Testing the _check_fields() method """
  81. from dyncode import Publication, Numero, LeObject, Personnes
  82. #Valid fields given
  83. LeObject._check_fields(None, Publication, Publication._fieldtypes.keys())
  84. LeObject._check_fields(Numero, None, Numero._fields)
  85. #Specials fields
  86. LeObject._check_fields(Numero, Publication, ['lodel_id'])
  87. #Common fields
  88. LeObject._check_fields(None, None, EditorialModel.classtypes.common_fields.keys())
  89. #Invalid fields
  90. with self.assertRaises(leapi.leobject.LeObjectQueryError):
  91. LeObject._check_fields(None, None, Numero._fields)
  92. class LeObjectMockDatasourceTestCase(TestCase):
  93. """ Testing _LeObject using a mock on the datasource """
  94. @classmethod
  95. def setUpClass(cls):
  96. """ Write the generated code in a temporary directory and import it """
  97. cls.tmpdir = leapi.test.utils.tmp_load_factory_code()
  98. @classmethod
  99. def tearDownClass(cls):
  100. """ Remove the temporary directory created at class setup """
  101. leapi.test.utils.cleanup(cls.tmpdir)
  102. @unittest.skip("Wait reimplementation in lecrud")
  103. @patch('leapi.datasources.dummy.DummyDatasource.insert')
  104. def test_insert(self, dsmock):
  105. from dyncode import Publication, Numero, LeObject
  106. ndatas = [
  107. [{'titre' : 'FooBar'}],
  108. [{'titre':'hello'},{'titre':'world'}],
  109. ]
  110. for ndats in ndatas:
  111. LeObject.insert(Numero,ndats)
  112. dsmock.assert_called_once_with(Numero, Publication, ndats)
  113. dsmock.reset_mock()
  114. LeObject.insert('Numero',ndats)
  115. dsmock.assert_called_once_with(Numero, Publication, ndats)
  116. dsmock.reset_mock()
  117. @unittest.skip("Wait reimplementation in lecrud")
  118. @patch('leapi.datasources.dummy.DummyDatasource.update')
  119. def test_update(self, dsmock):
  120. from dyncode import Publication, Numero, LeObject
  121. args = [
  122. ( ['lodel_id = 1'],
  123. {'titre':'foobar'},
  124. [('lodel_id','=','1')],
  125. []
  126. ),
  127. ( ['superior.parent in [1,2,3,4,5,6]', 'titre != "FooBar"'],
  128. {'titre':'FooBar'},
  129. [( 'titre','!=','"FooBar"')],
  130. [( (leapi.leobject.REL_SUP, 'parent') ,' in ', '[1,2,3,4,5,6]')]
  131. ),
  132. ]
  133. for filters, datas, ds_filters, ds_relfilters in args:
  134. LeObject.update(Numero, filters, datas)
  135. dsmock.assert_called_once_with(Numero, Publication, ds_filters, ds_relfilters, datas)
  136. dsmock.reset_mock()
  137. LeObject.update('Numero', filters, datas)
  138. dsmock.assert_called_once_with(Numero, Publication, ds_filters, ds_relfilters, datas)
  139. dsmock.reset_mock()
  140. @unittest.skip("Wait reimplementation in lecrud")
  141. @patch('leapi.datasources.dummy.DummyDatasource.delete')
  142. def test_delete(self, dsmock):
  143. from dyncode import Publication, Numero, LeObject
  144. args = [
  145. (
  146. ['lodel_id=1'],
  147. [('lodel_id', '=', '1')],
  148. []
  149. ),
  150. (
  151. ['subordinate.parent not in [1,2,3]', 'titre = "titre nul"'],
  152. [('titre','=', '"titre nul"')],
  153. [( (leapi.leobject.REL_SUB, 'parent'), ' not in ', '[1,2,3]')]
  154. ),
  155. ]
  156. for filters, ds_filters, ds_relfilters in args:
  157. LeObject.delete(Numero, filters)
  158. dsmock.assert_called_once_with(Numero, Publication, ds_filters, ds_relfilters)
  159. dsmock.reset_mock()
  160. LeObject.delete('Numero', filters)
  161. dsmock.assert_called_once_with(Numero, Publication, ds_filters, ds_relfilters)
  162. dsmock.reset_mock()
  163. @patch('leapi.datasources.dummy.DummyDatasource.get')
  164. @unittest.skip('Dummy datasource doesn\'t fit anymore')
  165. def test_get(self, dsmock):
  166. from dyncode import Publication, Numero, LeObject
  167. args = [
  168. (
  169. ['lodel_id', 'superior.parent'],
  170. ['titre != "foobar"'],
  171. ['lodel_id', (leapi.leobject.REL_SUP, 'parent')],
  172. [('titre','!=', '"foobar"')],
  173. []
  174. ),
  175. (
  176. ['lodel_id', 'titre', 'superior.parent', 'subordinate.translation'],
  177. ['superior.parent in [1,2,3,4,5]'],
  178. ['lodel_id', 'titre', (leapi.leobject.REL_SUP,'parent'), (leapi.leobject.REL_SUB, 'translation')],
  179. [],
  180. [( (leapi.leobject.REL_SUP, 'parent'), ' in ', '[1,2,3,4,5]')]
  181. ),
  182. (
  183. [],
  184. [],
  185. Numero._fields,
  186. [],
  187. []
  188. ),
  189. ]
  190. for field_list, filters, fl_ds, filters_ds, rfilters_ds in args:
  191. LeObject.get(filters, field_list, Numero)
  192. dsmock.assert_called_with(Publication, Numero, fl_ds, filters_ds, rfilters_ds)
  193. dsmock.reset_mock()
  194. @patch('leapi.datasources.dummy.DummyDatasource.get')
  195. @unittest.skip('Dummy datasource doesn\'t fit anymore')
  196. def test_get_incomplete_target(self, dsmock):
  197. """ Testing LeObject.get() method with partial target specifier """
  198. from dyncode import Publication, Numero, LeObject
  199. args = [
  200. (
  201. ['lodel_id'],
  202. [],
  203. None,
  204. None,
  205. ['lodel_id', 'type_id'],
  206. [],
  207. [],
  208. None,
  209. None
  210. ),
  211. (
  212. [],
  213. [],
  214. None,
  215. None,
  216. list(EditorialModel.classtypes.common_fields.keys()),
  217. [],
  218. [],
  219. None,
  220. None
  221. ),
  222. (
  223. ['lodel_id'],
  224. [],
  225. None,
  226. Publication,
  227. ['lodel_id', 'type_id'],
  228. [],
  229. [],
  230. None,
  231. Publication
  232. ),
  233. (
  234. [],
  235. [],
  236. Numero,
  237. None,
  238. Numero._fields,
  239. [],
  240. [],
  241. Numero,
  242. Publication
  243. ),
  244. ]
  245. for field_list, filters, letype, leclass, fl_ds, filters_ds, rfilters_ds, letype_ds, leclass_ds in args:
  246. LeObject.get(filters, field_list, letype, leclass)
  247. dsmock.assert_called_with(leclass_ds, letype_ds, fl_ds, filters_ds, rfilters_ds)
  248. dsmock.reset_mock()